From 9e8914c798648a3c554cb5745a72b4f1465208b8 Mon Sep 17 00:00:00 2001 From: Mojtaba Eshghie Date: Wed, 4 Sep 2024 23:17:03 +0200 Subject: [PATCH] #5 Batch 121 --- .../1/CCD/ERC20VotesCompMock.sol | 21 + .../1/DLR/ERC20VotesCompMock.sol | 21 + .../1/FVR/ERC20VotesCompMock.sol | 21 + .../1/MOC/ERC20VotesCompMock.sol | 21 + .../1/MOD/ERC20VotesCompMock.sol | 21 + .../1/RSD/ERC20VotesCompMock.sol | 21 + .../2/DLR/ERC20VotesCompMock.sol | 21 + .../2/FVR/ERC20VotesCompMock.sol | 21 + .../3/FVR/ERC20VotesCompMock.sol | 21 + .../original/ERC20VotesCompMock.sol | 21 + .../1/DLR/ERC20VotesCompMockUpgradeable.sol | 35 ++ .../1/FVR/ERC20VotesCompMockUpgradeable.sol | 35 ++ .../1/ILR/ERC20VotesCompMockUpgradeable.sol | 35 ++ .../1/MOI/ERC20VotesCompMockUpgradeable.sol | 35 ++ .../1/RSD/ERC20VotesCompMockUpgradeable.sol | 35 ++ .../1/SLR/ERC20VotesCompMockUpgradeable.sol | 35 ++ .../1/VVR/ERC20VotesCompMockUpgradeable.sol | 35 ++ .../2/DLR/ERC20VotesCompMockUpgradeable.sol | 35 ++ .../2/FVR/ERC20VotesCompMockUpgradeable.sol | 35 ++ .../2/MOI/ERC20VotesCompMockUpgradeable.sol | 35 ++ .../3/DLR/ERC20VotesCompMockUpgradeable.sol | 35 ++ .../3/FVR/ERC20VotesCompMockUpgradeable.sol | 35 ++ .../4/DLR/ERC20VotesCompMockUpgradeable.sol | 35 ++ .../4/FVR/ERC20VotesCompMockUpgradeable.sol | 35 ++ .../5/FVR/ERC20VotesCompMockUpgradeable.sol | 35 ++ .../ERC20VotesCompMockUpgradeable.sol | 35 ++ .../1/FVR/ERC20VotesCompUpgradeable.sol | 59 +++ .../1/ILR/ERC20VotesCompUpgradeable.sol | 59 +++ .../1/ORFD/ERC20VotesCompUpgradeable.sol | 57 +++ .../1/RSD/ERC20VotesCompUpgradeable.sol | 59 +++ .../1/VVR/ERC20VotesCompUpgradeable.sol | 59 +++ .../2/FVR/ERC20VotesCompUpgradeable.sol | 59 +++ .../2/RSD/ERC20VotesCompUpgradeable.sol | 59 +++ .../3/RSD/ERC20VotesCompUpgradeable.sol | 59 +++ .../original/ERC20VotesCompUpgradeable.sol | 59 +++ .../1/AOR/ERC20VotesHarness.sol | 28 ++ .../1/AVR/ERC20VotesHarness.sol | 28 ++ .../1/CCD/ERC20VotesHarness.sol | 28 ++ .../1/DLR/ERC20VotesHarness.sol | 28 ++ .../1/GVR/ERC20VotesHarness.sol | 28 ++ .../1/ICM/ERC20VotesHarness.sol | 28 ++ .../1/MOC/ERC20VotesHarness.sol | 28 ++ .../1/MOD/ERC20VotesHarness.sol | 28 ++ .../1/ORFD/ERC20VotesHarness.sol | 20 + .../1/SKD/ERC20VotesHarness.sol | 28 ++ .../2/AOR/ERC20VotesHarness.sol | 28 ++ .../2/AVR/ERC20VotesHarness.sol | 28 ++ .../2/DLR/ERC20VotesHarness.sol | 28 ++ .../2/GVR/ERC20VotesHarness.sol | 28 ++ .../2/ICM/ERC20VotesHarness.sol | 28 ++ .../2/ORFD/ERC20VotesHarness.sol | 16 + .../2/SKD/ERC20VotesHarness.sol | 28 ++ .../3/AOR/ERC20VotesHarness.sol | 28 ++ .../3/AVR/ERC20VotesHarness.sol | 28 ++ .../3/GVR/ERC20VotesHarness.sol | 28 ++ .../4/AOR/ERC20VotesHarness.sol | 28 ++ .../4/AVR/ERC20VotesHarness.sol | 28 ++ .../4/GVR/ERC20VotesHarness.sol | 28 ++ .../original/ERC20VotesHarness.sol | 28 ++ .../ERC20VotesMock/1/CCD/ERC20VotesMock.sol | 21 + .../ERC20VotesMock/1/DLR/ERC20VotesMock.sol | 21 + .../ERC20VotesMock/1/FVR/ERC20VotesMock.sol | 21 + .../ERC20VotesMock/1/MOC/ERC20VotesMock.sol | 21 + .../ERC20VotesMock/1/MOD/ERC20VotesMock.sol | 21 + .../ERC20VotesMock/1/RSD/ERC20VotesMock.sol | 21 + .../ERC20VotesMock/2/DLR/ERC20VotesMock.sol | 21 + .../ERC20VotesMock/2/FVR/ERC20VotesMock.sol | 21 + .../ERC20VotesMock/3/FVR/ERC20VotesMock.sol | 21 + .../original/ERC20VotesMock.sol | 21 + .../1/DLR/ERC20VotesMockUpgradeable.sol | 35 ++ .../1/FVR/ERC20VotesMockUpgradeable.sol | 35 ++ .../1/ILR/ERC20VotesMockUpgradeable.sol | 35 ++ .../1/MOI/ERC20VotesMockUpgradeable.sol | 35 ++ .../1/RSD/ERC20VotesMockUpgradeable.sol | 35 ++ .../1/SLR/ERC20VotesMockUpgradeable.sol | 35 ++ .../1/VVR/ERC20VotesMockUpgradeable.sol | 35 ++ .../2/DLR/ERC20VotesMockUpgradeable.sol | 35 ++ .../2/FVR/ERC20VotesMockUpgradeable.sol | 35 ++ .../2/MOI/ERC20VotesMockUpgradeable.sol | 35 ++ .../3/DLR/ERC20VotesMockUpgradeable.sol | 35 ++ .../3/FVR/ERC20VotesMockUpgradeable.sol | 35 ++ .../4/DLR/ERC20VotesMockUpgradeable.sol | 35 ++ .../4/FVR/ERC20VotesMockUpgradeable.sol | 35 ++ .../5/FVR/ERC20VotesMockUpgradeable.sol | 35 ++ .../original/ERC20VotesMockUpgradeable.sol | 35 ++ .../1/BOR/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../1/CSC/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../1/DLR/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../1/EED/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../1/EHC/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../1/FVR/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../1/GVR/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../1/ILR/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../1/MCR/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../1/MOI/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../1/ORFD/ERC20VotesUpgradeable.sol | 260 +++++++++++ .../1/RSD/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../1/RVS/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../1/SCEC/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../1/SKD/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../1/SKI/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../1/SLR/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../1/VVR/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../10/BOR/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../10/ILR/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../10/RSD/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../2/BOR/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../2/CSC/ERC20VotesUpgradeable.sol | 260 +++++++++++ .../2/DLR/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../2/EED/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../2/EHC/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../2/FVR/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../2/GVR/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../2/ILR/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../2/MCR/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../2/MOI/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../2/ORFD/ERC20VotesUpgradeable.sol | 257 +++++++++++ .../2/RSD/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../2/SKD/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../2/SKI/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../2/VVR/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../3/BOR/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../3/CSC/ERC20VotesUpgradeable.sol | 260 +++++++++++ .../3/DLR/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../3/EED/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../3/EHC/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../3/FVR/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../3/GVR/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../3/ILR/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../3/MOI/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../3/ORFD/ERC20VotesUpgradeable.sol | 254 +++++++++++ .../3/RSD/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../3/SKD/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../3/SKI/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../3/VVR/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../4/BOR/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../4/CSC/ERC20VotesUpgradeable.sol | 260 +++++++++++ .../4/EHC/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../4/FVR/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../4/GVR/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../4/ILR/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../4/MOI/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../4/ORFD/ERC20VotesUpgradeable.sol | 251 +++++++++++ .../4/RSD/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../5/BOR/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../5/CSC/ERC20VotesUpgradeable.sol | 260 +++++++++++ .../5/EHC/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../5/FVR/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../5/GVR/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../5/ILR/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../5/MOI/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../5/ORFD/ERC20VotesUpgradeable.sol | 249 ++++++++++ .../5/RSD/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../6/BOR/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../6/CSC/ERC20VotesUpgradeable.sol | 260 +++++++++++ .../6/FVR/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../6/ILR/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../6/MOI/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../6/ORFD/ERC20VotesUpgradeable.sol | 232 ++++++++++ .../6/RSD/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../7/BOR/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../7/CSC/ERC20VotesUpgradeable.sol | 258 +++++++++++ .../7/FVR/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../7/ILR/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../7/MOI/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../7/ORFD/ERC20VotesUpgradeable.sol | 227 ++++++++++ .../7/RSD/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../8/BOR/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../8/ILR/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../8/MOI/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../8/ORFD/ERC20VotesUpgradeable.sol | 223 +++++++++ .../8/RSD/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../9/BOR/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../9/ILR/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../9/ORFD/ERC20VotesUpgradeable.sol | 215 +++++++++ .../9/RSD/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../original/ERC20VotesUpgradeable.sol | 262 +++++++++++ .../ERC20WithFees/1/AOR/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/1/AVR/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/1/BLR/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/1/BOR/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/1/CCD/ERC20WithFees.sol | 421 +++++++++++++++++ .../ERC20WithFees/1/CSC/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/1/DLR/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/1/EED/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/1/EHC/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/1/FVR/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/1/ICM/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/1/ILR/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/1/LSC/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/1/ORFD/ERC20WithFees.sol | 422 +++++++++++++++++ .../ERC20WithFees/1/RSD/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/1/UORD/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/1/VVR/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/10/BOR/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/10/EHC/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/10/ILR/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/10/RSD/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/2/AOR/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/2/AVR/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/2/BLR/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/2/BOR/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/2/CSC/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/2/DLR/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/2/EED/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/2/EHC/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/2/FVR/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/2/ILR/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/2/ORFD/ERC20WithFees.sol | 420 +++++++++++++++++ .../ERC20WithFees/2/RSD/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/2/UORD/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/2/VVR/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/3/AOR/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/3/AVR/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/3/BLR/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/3/BOR/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/3/CSC/ERC20WithFees.sol | 422 +++++++++++++++++ .../ERC20WithFees/3/DLR/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/3/EED/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/3/EHC/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/3/FVR/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/3/ILR/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/3/ORFD/ERC20WithFees.sol | 418 +++++++++++++++++ .../ERC20WithFees/3/RSD/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/3/VVR/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/4/AOR/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/4/AVR/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/4/BLR/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/4/BOR/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/4/DLR/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/4/EED/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/4/EHC/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/4/ILR/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/4/ORFD/ERC20WithFees.sol | 416 +++++++++++++++++ .../ERC20WithFees/4/RSD/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/4/VVR/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/5/AOR/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/5/AVR/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/5/BLR/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/5/BOR/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/5/EED/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/5/EHC/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/5/ILR/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/5/ORFD/ERC20WithFees.sol | 414 +++++++++++++++++ .../ERC20WithFees/5/RSD/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/6/BOR/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/6/EED/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/6/EHC/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/6/ILR/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/6/ORFD/ERC20WithFees.sol | 411 +++++++++++++++++ .../ERC20WithFees/6/RSD/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/7/BOR/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/7/EED/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/7/EHC/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/7/ILR/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/7/ORFD/ERC20WithFees.sol | 409 +++++++++++++++++ .../ERC20WithFees/7/RSD/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/8/BOR/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/8/EHC/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/8/ILR/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/8/ORFD/ERC20WithFees.sol | 406 +++++++++++++++++ .../ERC20WithFees/8/RSD/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/9/BOR/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/9/EHC/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/9/ILR/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/9/ORFD/ERC20WithFees.sol | 392 ++++++++++++++++ .../ERC20WithFees/9/RSD/ERC20WithFees.sol | 424 ++++++++++++++++++ .../ERC20WithFees/original/ERC20WithFees.sol | 424 ++++++++++++++++++ .../1/CCD/ERC20WithMetadataMock.sol | 8 + .../1/FVR/ERC20WithMetadataMock.sol | 11 + .../original/ERC20WithMetadataMock.sol | 11 + .../ERC20WithSupply/1/AOR/ERC20WithSupply.sol | 21 + .../ERC20WithSupply/1/AVR/ERC20WithSupply.sol | 21 + .../ERC20WithSupply/1/BOR/ERC20WithSupply.sol | 21 + .../ERC20WithSupply/1/EED/ERC20WithSupply.sol | 21 + .../ERC20WithSupply/1/ICM/ERC20WithSupply.sol | 21 + .../ERC20WithSupply/1/ILR/ERC20WithSupply.sol | 21 + .../ERC20WithSupply/1/LSC/ERC20WithSupply.sol | 21 + .../1/ORFD/ERC20WithSupply.sol | 17 + .../ERC20WithSupply/1/VVR/ERC20WithSupply.sol | 21 + .../ERC20WithSupply/2/AOR/ERC20WithSupply.sol | 21 + .../ERC20WithSupply/2/AVR/ERC20WithSupply.sol | 21 + .../ERC20WithSupply/2/BOR/ERC20WithSupply.sol | 21 + .../ERC20WithSupply/2/EED/ERC20WithSupply.sol | 21 + .../ERC20WithSupply/2/ILR/ERC20WithSupply.sol | 21 + .../2/ORFD/ERC20WithSupply.sol | 13 + .../original/ERC20WithSupply.sol | 21 + 287 files changed, 65446 insertions(+) create mode 100644 contracts/mutants/ERC20VotesCompMock/1/CCD/ERC20VotesCompMock.sol create mode 100644 contracts/mutants/ERC20VotesCompMock/1/DLR/ERC20VotesCompMock.sol create mode 100644 contracts/mutants/ERC20VotesCompMock/1/FVR/ERC20VotesCompMock.sol create mode 100644 contracts/mutants/ERC20VotesCompMock/1/MOC/ERC20VotesCompMock.sol create mode 100644 contracts/mutants/ERC20VotesCompMock/1/MOD/ERC20VotesCompMock.sol create mode 100644 contracts/mutants/ERC20VotesCompMock/1/RSD/ERC20VotesCompMock.sol create mode 100644 contracts/mutants/ERC20VotesCompMock/2/DLR/ERC20VotesCompMock.sol create mode 100644 contracts/mutants/ERC20VotesCompMock/2/FVR/ERC20VotesCompMock.sol create mode 100644 contracts/mutants/ERC20VotesCompMock/3/FVR/ERC20VotesCompMock.sol create mode 100644 contracts/mutants/ERC20VotesCompMock/original/ERC20VotesCompMock.sol create mode 100644 contracts/mutants/ERC20VotesCompMockUpgradeable/1/DLR/ERC20VotesCompMockUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesCompMockUpgradeable/1/FVR/ERC20VotesCompMockUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesCompMockUpgradeable/1/ILR/ERC20VotesCompMockUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesCompMockUpgradeable/1/MOI/ERC20VotesCompMockUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesCompMockUpgradeable/1/RSD/ERC20VotesCompMockUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesCompMockUpgradeable/1/SLR/ERC20VotesCompMockUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesCompMockUpgradeable/1/VVR/ERC20VotesCompMockUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesCompMockUpgradeable/2/DLR/ERC20VotesCompMockUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesCompMockUpgradeable/2/FVR/ERC20VotesCompMockUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesCompMockUpgradeable/2/MOI/ERC20VotesCompMockUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesCompMockUpgradeable/3/DLR/ERC20VotesCompMockUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesCompMockUpgradeable/3/FVR/ERC20VotesCompMockUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesCompMockUpgradeable/4/DLR/ERC20VotesCompMockUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesCompMockUpgradeable/4/FVR/ERC20VotesCompMockUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesCompMockUpgradeable/5/FVR/ERC20VotesCompMockUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesCompMockUpgradeable/original/ERC20VotesCompMockUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesCompUpgradeable/1/FVR/ERC20VotesCompUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesCompUpgradeable/1/ILR/ERC20VotesCompUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesCompUpgradeable/1/ORFD/ERC20VotesCompUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesCompUpgradeable/1/RSD/ERC20VotesCompUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesCompUpgradeable/1/VVR/ERC20VotesCompUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesCompUpgradeable/2/FVR/ERC20VotesCompUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesCompUpgradeable/2/RSD/ERC20VotesCompUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesCompUpgradeable/3/RSD/ERC20VotesCompUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesCompUpgradeable/original/ERC20VotesCompUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesHarness/1/AOR/ERC20VotesHarness.sol create mode 100644 contracts/mutants/ERC20VotesHarness/1/AVR/ERC20VotesHarness.sol create mode 100644 contracts/mutants/ERC20VotesHarness/1/CCD/ERC20VotesHarness.sol create mode 100644 contracts/mutants/ERC20VotesHarness/1/DLR/ERC20VotesHarness.sol create mode 100644 contracts/mutants/ERC20VotesHarness/1/GVR/ERC20VotesHarness.sol create mode 100644 contracts/mutants/ERC20VotesHarness/1/ICM/ERC20VotesHarness.sol create mode 100644 contracts/mutants/ERC20VotesHarness/1/MOC/ERC20VotesHarness.sol create mode 100644 contracts/mutants/ERC20VotesHarness/1/MOD/ERC20VotesHarness.sol create mode 100644 contracts/mutants/ERC20VotesHarness/1/ORFD/ERC20VotesHarness.sol create mode 100644 contracts/mutants/ERC20VotesHarness/1/SKD/ERC20VotesHarness.sol create mode 100644 contracts/mutants/ERC20VotesHarness/2/AOR/ERC20VotesHarness.sol create mode 100644 contracts/mutants/ERC20VotesHarness/2/AVR/ERC20VotesHarness.sol create mode 100644 contracts/mutants/ERC20VotesHarness/2/DLR/ERC20VotesHarness.sol create mode 100644 contracts/mutants/ERC20VotesHarness/2/GVR/ERC20VotesHarness.sol create mode 100644 contracts/mutants/ERC20VotesHarness/2/ICM/ERC20VotesHarness.sol create mode 100644 contracts/mutants/ERC20VotesHarness/2/ORFD/ERC20VotesHarness.sol create mode 100644 contracts/mutants/ERC20VotesHarness/2/SKD/ERC20VotesHarness.sol create mode 100644 contracts/mutants/ERC20VotesHarness/3/AOR/ERC20VotesHarness.sol create mode 100644 contracts/mutants/ERC20VotesHarness/3/AVR/ERC20VotesHarness.sol create mode 100644 contracts/mutants/ERC20VotesHarness/3/GVR/ERC20VotesHarness.sol create mode 100644 contracts/mutants/ERC20VotesHarness/4/AOR/ERC20VotesHarness.sol create mode 100644 contracts/mutants/ERC20VotesHarness/4/AVR/ERC20VotesHarness.sol create mode 100644 contracts/mutants/ERC20VotesHarness/4/GVR/ERC20VotesHarness.sol create mode 100644 contracts/mutants/ERC20VotesHarness/original/ERC20VotesHarness.sol create mode 100644 contracts/mutants/ERC20VotesMock/1/CCD/ERC20VotesMock.sol create mode 100644 contracts/mutants/ERC20VotesMock/1/DLR/ERC20VotesMock.sol create mode 100644 contracts/mutants/ERC20VotesMock/1/FVR/ERC20VotesMock.sol create mode 100644 contracts/mutants/ERC20VotesMock/1/MOC/ERC20VotesMock.sol create mode 100644 contracts/mutants/ERC20VotesMock/1/MOD/ERC20VotesMock.sol create mode 100644 contracts/mutants/ERC20VotesMock/1/RSD/ERC20VotesMock.sol create mode 100644 contracts/mutants/ERC20VotesMock/2/DLR/ERC20VotesMock.sol create mode 100644 contracts/mutants/ERC20VotesMock/2/FVR/ERC20VotesMock.sol create mode 100644 contracts/mutants/ERC20VotesMock/3/FVR/ERC20VotesMock.sol create mode 100644 contracts/mutants/ERC20VotesMock/original/ERC20VotesMock.sol create mode 100644 contracts/mutants/ERC20VotesMockUpgradeable/1/DLR/ERC20VotesMockUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesMockUpgradeable/1/FVR/ERC20VotesMockUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesMockUpgradeable/1/ILR/ERC20VotesMockUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesMockUpgradeable/1/MOI/ERC20VotesMockUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesMockUpgradeable/1/RSD/ERC20VotesMockUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesMockUpgradeable/1/SLR/ERC20VotesMockUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesMockUpgradeable/1/VVR/ERC20VotesMockUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesMockUpgradeable/2/DLR/ERC20VotesMockUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesMockUpgradeable/2/FVR/ERC20VotesMockUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesMockUpgradeable/2/MOI/ERC20VotesMockUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesMockUpgradeable/3/DLR/ERC20VotesMockUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesMockUpgradeable/3/FVR/ERC20VotesMockUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesMockUpgradeable/4/DLR/ERC20VotesMockUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesMockUpgradeable/4/FVR/ERC20VotesMockUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesMockUpgradeable/5/FVR/ERC20VotesMockUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesMockUpgradeable/original/ERC20VotesMockUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/1/BOR/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/1/CSC/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/1/DLR/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/1/EED/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/1/EHC/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/1/FVR/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/1/GVR/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/1/ILR/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/1/MCR/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/1/MOI/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/1/ORFD/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/1/RSD/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/1/RVS/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/1/SCEC/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/1/SKD/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/1/SKI/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/1/SLR/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/1/VVR/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/10/BOR/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/10/ILR/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/10/RSD/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/2/BOR/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/2/CSC/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/2/DLR/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/2/EED/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/2/EHC/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/2/FVR/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/2/GVR/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/2/ILR/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/2/MCR/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/2/MOI/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/2/ORFD/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/2/RSD/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/2/SKD/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/2/SKI/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/2/VVR/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/3/BOR/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/3/CSC/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/3/DLR/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/3/EED/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/3/EHC/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/3/FVR/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/3/GVR/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/3/ILR/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/3/MOI/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/3/ORFD/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/3/RSD/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/3/SKD/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/3/SKI/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/3/VVR/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/4/BOR/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/4/CSC/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/4/EHC/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/4/FVR/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/4/GVR/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/4/ILR/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/4/MOI/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/4/ORFD/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/4/RSD/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/5/BOR/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/5/CSC/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/5/EHC/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/5/FVR/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/5/GVR/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/5/ILR/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/5/MOI/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/5/ORFD/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/5/RSD/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/6/BOR/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/6/CSC/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/6/FVR/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/6/ILR/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/6/MOI/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/6/ORFD/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/6/RSD/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/7/BOR/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/7/CSC/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/7/FVR/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/7/ILR/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/7/MOI/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/7/ORFD/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/7/RSD/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/8/BOR/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/8/ILR/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/8/MOI/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/8/ORFD/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/8/RSD/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/9/BOR/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/9/ILR/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/9/ORFD/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/9/RSD/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20VotesUpgradeable/original/ERC20VotesUpgradeable.sol create mode 100644 contracts/mutants/ERC20WithFees/1/AOR/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/1/AVR/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/1/BLR/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/1/BOR/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/1/CCD/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/1/CSC/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/1/DLR/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/1/EED/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/1/EHC/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/1/FVR/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/1/ICM/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/1/ILR/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/1/LSC/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/1/ORFD/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/1/RSD/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/1/UORD/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/1/VVR/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/10/BOR/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/10/EHC/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/10/ILR/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/10/RSD/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/2/AOR/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/2/AVR/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/2/BLR/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/2/BOR/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/2/CSC/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/2/DLR/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/2/EED/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/2/EHC/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/2/FVR/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/2/ILR/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/2/ORFD/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/2/RSD/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/2/UORD/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/2/VVR/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/3/AOR/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/3/AVR/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/3/BLR/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/3/BOR/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/3/CSC/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/3/DLR/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/3/EED/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/3/EHC/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/3/FVR/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/3/ILR/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/3/ORFD/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/3/RSD/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/3/VVR/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/4/AOR/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/4/AVR/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/4/BLR/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/4/BOR/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/4/DLR/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/4/EED/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/4/EHC/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/4/ILR/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/4/ORFD/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/4/RSD/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/4/VVR/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/5/AOR/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/5/AVR/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/5/BLR/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/5/BOR/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/5/EED/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/5/EHC/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/5/ILR/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/5/ORFD/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/5/RSD/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/6/BOR/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/6/EED/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/6/EHC/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/6/ILR/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/6/ORFD/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/6/RSD/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/7/BOR/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/7/EED/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/7/EHC/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/7/ILR/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/7/ORFD/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/7/RSD/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/8/BOR/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/8/EHC/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/8/ILR/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/8/ORFD/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/8/RSD/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/9/BOR/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/9/EHC/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/9/ILR/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/9/ORFD/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/9/RSD/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithFees/original/ERC20WithFees.sol create mode 100644 contracts/mutants/ERC20WithMetadataMock/1/CCD/ERC20WithMetadataMock.sol create mode 100644 contracts/mutants/ERC20WithMetadataMock/1/FVR/ERC20WithMetadataMock.sol create mode 100644 contracts/mutants/ERC20WithMetadataMock/original/ERC20WithMetadataMock.sol create mode 100644 contracts/mutants/ERC20WithSupply/1/AOR/ERC20WithSupply.sol create mode 100644 contracts/mutants/ERC20WithSupply/1/AVR/ERC20WithSupply.sol create mode 100644 contracts/mutants/ERC20WithSupply/1/BOR/ERC20WithSupply.sol create mode 100644 contracts/mutants/ERC20WithSupply/1/EED/ERC20WithSupply.sol create mode 100644 contracts/mutants/ERC20WithSupply/1/ICM/ERC20WithSupply.sol create mode 100644 contracts/mutants/ERC20WithSupply/1/ILR/ERC20WithSupply.sol create mode 100644 contracts/mutants/ERC20WithSupply/1/LSC/ERC20WithSupply.sol create mode 100644 contracts/mutants/ERC20WithSupply/1/ORFD/ERC20WithSupply.sol create mode 100644 contracts/mutants/ERC20WithSupply/1/VVR/ERC20WithSupply.sol create mode 100644 contracts/mutants/ERC20WithSupply/2/AOR/ERC20WithSupply.sol create mode 100644 contracts/mutants/ERC20WithSupply/2/AVR/ERC20WithSupply.sol create mode 100644 contracts/mutants/ERC20WithSupply/2/BOR/ERC20WithSupply.sol create mode 100644 contracts/mutants/ERC20WithSupply/2/EED/ERC20WithSupply.sol create mode 100644 contracts/mutants/ERC20WithSupply/2/ILR/ERC20WithSupply.sol create mode 100644 contracts/mutants/ERC20WithSupply/2/ORFD/ERC20WithSupply.sol create mode 100644 contracts/mutants/ERC20WithSupply/original/ERC20WithSupply.sol diff --git a/contracts/mutants/ERC20VotesCompMock/1/CCD/ERC20VotesCompMock.sol b/contracts/mutants/ERC20VotesCompMock/1/CCD/ERC20VotesCompMock.sol new file mode 100644 index 00000000000..763d2b3363a --- /dev/null +++ b/contracts/mutants/ERC20VotesCompMock/1/CCD/ERC20VotesCompMock.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "../token/ERC20/extensions/ERC20VotesComp.sol"; + +contract ERC20VotesCompMock is ERC20VotesComp { + + + function mint(address account, uint256 amount) public { + _mint(account, amount); + } + + function burn(address account, uint256 amount) public { + _burn(account, amount); + } + + function getChainId() external view returns (uint256) { + return block.chainid; + } +} diff --git a/contracts/mutants/ERC20VotesCompMock/1/DLR/ERC20VotesCompMock.sol b/contracts/mutants/ERC20VotesCompMock/1/DLR/ERC20VotesCompMock.sol new file mode 100644 index 00000000000..e93277f0128 --- /dev/null +++ b/contracts/mutants/ERC20VotesCompMock/1/DLR/ERC20VotesCompMock.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "../token/ERC20/extensions/ERC20VotesComp.sol"; + +contract ERC20VotesCompMock is ERC20VotesComp { + constructor(string storage name, string memory symbol) ERC20(name, symbol) ERC20Permit(name) {} + + function mint(address account, uint256 amount) public { + _mint(account, amount); + } + + function burn(address account, uint256 amount) public { + _burn(account, amount); + } + + function getChainId() external view returns (uint256) { + return block.chainid; + } +} diff --git a/contracts/mutants/ERC20VotesCompMock/1/FVR/ERC20VotesCompMock.sol b/contracts/mutants/ERC20VotesCompMock/1/FVR/ERC20VotesCompMock.sol new file mode 100644 index 00000000000..91586ce621b --- /dev/null +++ b/contracts/mutants/ERC20VotesCompMock/1/FVR/ERC20VotesCompMock.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "../token/ERC20/extensions/ERC20VotesComp.sol"; + +contract ERC20VotesCompMock is ERC20VotesComp { + constructor(string memory name, string memory symbol) ERC20(name, symbol) ERC20Permit(name) {} + + function mint(address account, uint256 amount) external { + _mint(account, amount); + } + + function burn(address account, uint256 amount) public { + _burn(account, amount); + } + + function getChainId() external view returns (uint256) { + return block.chainid; + } +} diff --git a/contracts/mutants/ERC20VotesCompMock/1/MOC/ERC20VotesCompMock.sol b/contracts/mutants/ERC20VotesCompMock/1/MOC/ERC20VotesCompMock.sol new file mode 100644 index 00000000000..bc140627cb9 --- /dev/null +++ b/contracts/mutants/ERC20VotesCompMock/1/MOC/ERC20VotesCompMock.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "../token/ERC20/extensions/ERC20VotesComp.sol"; + +contract ERC20VotesCompMock is ERC20VotesComp { + constructor(string memory name, string memory symbol) ERC20Permit(name) ERC20(name, symbol) {} + + function mint(address account, uint256 amount) public { + _mint(account, amount); + } + + function burn(address account, uint256 amount) public { + _burn(account, amount); + } + + function getChainId() external view returns (uint256) { + return block.chainid; + } +} diff --git a/contracts/mutants/ERC20VotesCompMock/1/MOD/ERC20VotesCompMock.sol b/contracts/mutants/ERC20VotesCompMock/1/MOD/ERC20VotesCompMock.sol new file mode 100644 index 00000000000..6768a9b09c7 --- /dev/null +++ b/contracts/mutants/ERC20VotesCompMock/1/MOD/ERC20VotesCompMock.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "../token/ERC20/extensions/ERC20VotesComp.sol"; + +contract ERC20VotesCompMock is ERC20VotesComp { + constructor(string memory name, string memory symbol) ERC20Permit(name) {} + + function mint(address account, uint256 amount) public { + _mint(account, amount); + } + + function burn(address account, uint256 amount) public { + _burn(account, amount); + } + + function getChainId() external view returns (uint256) { + return block.chainid; + } +} diff --git a/contracts/mutants/ERC20VotesCompMock/1/RSD/ERC20VotesCompMock.sol b/contracts/mutants/ERC20VotesCompMock/1/RSD/ERC20VotesCompMock.sol new file mode 100644 index 00000000000..88b8102a427 --- /dev/null +++ b/contracts/mutants/ERC20VotesCompMock/1/RSD/ERC20VotesCompMock.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "../token/ERC20/extensions/ERC20VotesComp.sol"; + +contract ERC20VotesCompMock is ERC20VotesComp { + constructor(string memory name, string memory symbol) ERC20(name, symbol) ERC20Permit(name) {} + + function mint(address account, uint256 amount) public { + _mint(account, amount); + } + + function burn(address account, uint256 amount) public { + _burn(account, amount); + } + + function getChainId() external view returns (uint256) { + /* return block.chainid; */ + } +} diff --git a/contracts/mutants/ERC20VotesCompMock/2/DLR/ERC20VotesCompMock.sol b/contracts/mutants/ERC20VotesCompMock/2/DLR/ERC20VotesCompMock.sol new file mode 100644 index 00000000000..c9532d2f5a3 --- /dev/null +++ b/contracts/mutants/ERC20VotesCompMock/2/DLR/ERC20VotesCompMock.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "../token/ERC20/extensions/ERC20VotesComp.sol"; + +contract ERC20VotesCompMock is ERC20VotesComp { + constructor(string storage name, string storage symbol) ERC20(name, symbol) ERC20Permit(name) {} + + function mint(address account, uint256 amount) public { + _mint(account, amount); + } + + function burn(address account, uint256 amount) public { + _burn(account, amount); + } + + function getChainId() external view returns (uint256) { + return block.chainid; + } +} diff --git a/contracts/mutants/ERC20VotesCompMock/2/FVR/ERC20VotesCompMock.sol b/contracts/mutants/ERC20VotesCompMock/2/FVR/ERC20VotesCompMock.sol new file mode 100644 index 00000000000..2e60a6265dc --- /dev/null +++ b/contracts/mutants/ERC20VotesCompMock/2/FVR/ERC20VotesCompMock.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "../token/ERC20/extensions/ERC20VotesComp.sol"; + +contract ERC20VotesCompMock is ERC20VotesComp { + constructor(string memory name, string memory symbol) ERC20(name, symbol) ERC20Permit(name) {} + + function mint(address account, uint256 amount) external { + _mint(account, amount); + } + + function burn(address account, uint256 amount) external { + _burn(account, amount); + } + + function getChainId() external view returns (uint256) { + return block.chainid; + } +} diff --git a/contracts/mutants/ERC20VotesCompMock/3/FVR/ERC20VotesCompMock.sol b/contracts/mutants/ERC20VotesCompMock/3/FVR/ERC20VotesCompMock.sol new file mode 100644 index 00000000000..054693c6193 --- /dev/null +++ b/contracts/mutants/ERC20VotesCompMock/3/FVR/ERC20VotesCompMock.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "../token/ERC20/extensions/ERC20VotesComp.sol"; + +contract ERC20VotesCompMock is ERC20VotesComp { + constructor(string memory name, string memory symbol) ERC20(name, symbol) ERC20Permit(name) {} + + function mint(address account, uint256 amount) external { + _mint(account, amount); + } + + function burn(address account, uint256 amount) external { + _burn(account, amount); + } + + function getChainId() public view returns (uint256) { + return block.chainid; + } +} diff --git a/contracts/mutants/ERC20VotesCompMock/original/ERC20VotesCompMock.sol b/contracts/mutants/ERC20VotesCompMock/original/ERC20VotesCompMock.sol new file mode 100644 index 00000000000..171071fd500 --- /dev/null +++ b/contracts/mutants/ERC20VotesCompMock/original/ERC20VotesCompMock.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "../token/ERC20/extensions/ERC20VotesComp.sol"; + +contract ERC20VotesCompMock is ERC20VotesComp { + constructor(string memory name, string memory symbol) ERC20(name, symbol) ERC20Permit(name) {} + + function mint(address account, uint256 amount) public { + _mint(account, amount); + } + + function burn(address account, uint256 amount) public { + _burn(account, amount); + } + + function getChainId() external view returns (uint256) { + return block.chainid; + } +} diff --git a/contracts/mutants/ERC20VotesCompMockUpgradeable/1/DLR/ERC20VotesCompMockUpgradeable.sol b/contracts/mutants/ERC20VotesCompMockUpgradeable/1/DLR/ERC20VotesCompMockUpgradeable.sol new file mode 100644 index 00000000000..753c86402f2 --- /dev/null +++ b/contracts/mutants/ERC20VotesCompMockUpgradeable/1/DLR/ERC20VotesCompMockUpgradeable.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "../token/ERC20/extensions/ERC20VotesCompUpgradeable.sol"; +import "../proxy/utils/Initializable.sol"; + +contract ERC20VotesCompMockUpgradeable is Initializable, ERC20VotesCompUpgradeable { + function __ERC20VotesCompMock_init(string storage name, string memory symbol) internal onlyInitializing { + __ERC20_init_unchained(name, symbol); + __EIP712_init_unchained(name, "1"); + __ERC20Permit_init_unchained(name); + } + + function __ERC20VotesCompMock_init_unchained(string memory, string memory) internal onlyInitializing {} + + function mint(address account, uint256 amount) public { + _mint(account, amount); + } + + function burn(address account, uint256 amount) public { + _burn(account, amount); + } + + function getChainId() external view returns (uint256) { + return block.chainid; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[50] private __gap; +} diff --git a/contracts/mutants/ERC20VotesCompMockUpgradeable/1/FVR/ERC20VotesCompMockUpgradeable.sol b/contracts/mutants/ERC20VotesCompMockUpgradeable/1/FVR/ERC20VotesCompMockUpgradeable.sol new file mode 100644 index 00000000000..9fd9af76f0f --- /dev/null +++ b/contracts/mutants/ERC20VotesCompMockUpgradeable/1/FVR/ERC20VotesCompMockUpgradeable.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "../token/ERC20/extensions/ERC20VotesCompUpgradeable.sol"; +import "../proxy/utils/Initializable.sol"; + +contract ERC20VotesCompMockUpgradeable is Initializable, ERC20VotesCompUpgradeable { + function __ERC20VotesCompMock_init(string memory name, string memory symbol) public onlyInitializing { + __ERC20_init_unchained(name, symbol); + __EIP712_init_unchained(name, "1"); + __ERC20Permit_init_unchained(name); + } + + function __ERC20VotesCompMock_init_unchained(string memory, string memory) internal onlyInitializing {} + + function mint(address account, uint256 amount) public { + _mint(account, amount); + } + + function burn(address account, uint256 amount) public { + _burn(account, amount); + } + + function getChainId() external view returns (uint256) { + return block.chainid; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[50] private __gap; +} diff --git a/contracts/mutants/ERC20VotesCompMockUpgradeable/1/ILR/ERC20VotesCompMockUpgradeable.sol b/contracts/mutants/ERC20VotesCompMockUpgradeable/1/ILR/ERC20VotesCompMockUpgradeable.sol new file mode 100644 index 00000000000..7c941b3f6a8 --- /dev/null +++ b/contracts/mutants/ERC20VotesCompMockUpgradeable/1/ILR/ERC20VotesCompMockUpgradeable.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "../token/ERC20/extensions/ERC20VotesCompUpgradeable.sol"; +import "../proxy/utils/Initializable.sol"; + +contract ERC20VotesCompMockUpgradeable is Initializable, ERC20VotesCompUpgradeable { + function __ERC20VotesCompMock_init(string memory name, string memory symbol) internal onlyInitializing { + __ERC20_init_unchained(name, symbol); + __EIP712_init_unchained(name, "1"); + __ERC20Permit_init_unchained(name); + } + + function __ERC20VotesCompMock_init_unchained(string memory, string memory) internal onlyInitializing {} + + function mint(address account, uint256 amount) public { + _mint(account, amount); + } + + function burn(address account, uint256 amount) public { + _burn(account, amount); + } + + function getChainId() external view returns (uint256) { + return block.chainid; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[49] private __gap; +} diff --git a/contracts/mutants/ERC20VotesCompMockUpgradeable/1/MOI/ERC20VotesCompMockUpgradeable.sol b/contracts/mutants/ERC20VotesCompMockUpgradeable/1/MOI/ERC20VotesCompMockUpgradeable.sol new file mode 100644 index 00000000000..e12c2e91e83 --- /dev/null +++ b/contracts/mutants/ERC20VotesCompMockUpgradeable/1/MOI/ERC20VotesCompMockUpgradeable.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "../token/ERC20/extensions/ERC20VotesCompUpgradeable.sol"; +import "../proxy/utils/Initializable.sol"; + +contract ERC20VotesCompMockUpgradeable is Initializable, ERC20VotesCompUpgradeable { + function __ERC20VotesCompMock_init(string memory name, string memory symbol) internal onlyInitializing { + __ERC20_init_unchained(name, symbol); + __EIP712_init_unchained(name, "1"); + __ERC20Permit_init_unchained(name); + } + + function __ERC20VotesCompMock_init_unchained(string memory, string memory) internal onlyInitializing {} + + function mint(address account, uint256 amount) public onlyInitializing { + _mint(account, amount); + } + + function burn(address account, uint256 amount) public { + _burn(account, amount); + } + + function getChainId() external view returns (uint256) { + return block.chainid; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[50] private __gap; +} diff --git a/contracts/mutants/ERC20VotesCompMockUpgradeable/1/RSD/ERC20VotesCompMockUpgradeable.sol b/contracts/mutants/ERC20VotesCompMockUpgradeable/1/RSD/ERC20VotesCompMockUpgradeable.sol new file mode 100644 index 00000000000..d4ae4f9bf91 --- /dev/null +++ b/contracts/mutants/ERC20VotesCompMockUpgradeable/1/RSD/ERC20VotesCompMockUpgradeable.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "../token/ERC20/extensions/ERC20VotesCompUpgradeable.sol"; +import "../proxy/utils/Initializable.sol"; + +contract ERC20VotesCompMockUpgradeable is Initializable, ERC20VotesCompUpgradeable { + function __ERC20VotesCompMock_init(string memory name, string memory symbol) internal onlyInitializing { + __ERC20_init_unchained(name, symbol); + __EIP712_init_unchained(name, "1"); + __ERC20Permit_init_unchained(name); + } + + function __ERC20VotesCompMock_init_unchained(string memory, string memory) internal onlyInitializing {} + + function mint(address account, uint256 amount) public { + _mint(account, amount); + } + + function burn(address account, uint256 amount) public { + _burn(account, amount); + } + + function getChainId() external view returns (uint256) { + /* return block.chainid; */ + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[50] private __gap; +} diff --git a/contracts/mutants/ERC20VotesCompMockUpgradeable/1/SLR/ERC20VotesCompMockUpgradeable.sol b/contracts/mutants/ERC20VotesCompMockUpgradeable/1/SLR/ERC20VotesCompMockUpgradeable.sol new file mode 100644 index 00000000000..29ae354171a --- /dev/null +++ b/contracts/mutants/ERC20VotesCompMockUpgradeable/1/SLR/ERC20VotesCompMockUpgradeable.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "../token/ERC20/extensions/ERC20VotesCompUpgradeable.sol"; +import "../proxy/utils/Initializable.sol"; + +contract ERC20VotesCompMockUpgradeable is Initializable, ERC20VotesCompUpgradeable { + function __ERC20VotesCompMock_init(string memory name, string memory symbol) internal onlyInitializing { + __ERC20_init_unchained(name, symbol); + __EIP712_init_unchained(name, ""); + __ERC20Permit_init_unchained(name); + } + + function __ERC20VotesCompMock_init_unchained(string memory, string memory) internal onlyInitializing {} + + function mint(address account, uint256 amount) public { + _mint(account, amount); + } + + function burn(address account, uint256 amount) public { + _burn(account, amount); + } + + function getChainId() external view returns (uint256) { + return block.chainid; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[50] private __gap; +} diff --git a/contracts/mutants/ERC20VotesCompMockUpgradeable/1/VVR/ERC20VotesCompMockUpgradeable.sol b/contracts/mutants/ERC20VotesCompMockUpgradeable/1/VVR/ERC20VotesCompMockUpgradeable.sol new file mode 100644 index 00000000000..d512f058c0c --- /dev/null +++ b/contracts/mutants/ERC20VotesCompMockUpgradeable/1/VVR/ERC20VotesCompMockUpgradeable.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "../token/ERC20/extensions/ERC20VotesCompUpgradeable.sol"; +import "../proxy/utils/Initializable.sol"; + +contract ERC20VotesCompMockUpgradeable is Initializable, ERC20VotesCompUpgradeable { + function __ERC20VotesCompMock_init(string memory name, string memory symbol) internal onlyInitializing { + __ERC20_init_unchained(name, symbol); + __EIP712_init_unchained(name, "1"); + __ERC20Permit_init_unchained(name); + } + + function __ERC20VotesCompMock_init_unchained(string memory, string memory) internal onlyInitializing {} + + function mint(address account, uint256 amount) public { + _mint(account, amount); + } + + function burn(address account, uint256 amount) public { + _burn(account, amount); + } + + function getChainId() external view returns (uint256) { + return block.chainid; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[50] public __gap; +} diff --git a/contracts/mutants/ERC20VotesCompMockUpgradeable/2/DLR/ERC20VotesCompMockUpgradeable.sol b/contracts/mutants/ERC20VotesCompMockUpgradeable/2/DLR/ERC20VotesCompMockUpgradeable.sol new file mode 100644 index 00000000000..122c8ca8283 --- /dev/null +++ b/contracts/mutants/ERC20VotesCompMockUpgradeable/2/DLR/ERC20VotesCompMockUpgradeable.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "../token/ERC20/extensions/ERC20VotesCompUpgradeable.sol"; +import "../proxy/utils/Initializable.sol"; + +contract ERC20VotesCompMockUpgradeable is Initializable, ERC20VotesCompUpgradeable { + function __ERC20VotesCompMock_init(string storage name, string storage symbol) internal onlyInitializing { + __ERC20_init_unchained(name, symbol); + __EIP712_init_unchained(name, "1"); + __ERC20Permit_init_unchained(name); + } + + function __ERC20VotesCompMock_init_unchained(string memory, string memory) internal onlyInitializing {} + + function mint(address account, uint256 amount) public { + _mint(account, amount); + } + + function burn(address account, uint256 amount) public { + _burn(account, amount); + } + + function getChainId() external view returns (uint256) { + return block.chainid; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[50] private __gap; +} diff --git a/contracts/mutants/ERC20VotesCompMockUpgradeable/2/FVR/ERC20VotesCompMockUpgradeable.sol b/contracts/mutants/ERC20VotesCompMockUpgradeable/2/FVR/ERC20VotesCompMockUpgradeable.sol new file mode 100644 index 00000000000..23ef8bd3c54 --- /dev/null +++ b/contracts/mutants/ERC20VotesCompMockUpgradeable/2/FVR/ERC20VotesCompMockUpgradeable.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "../token/ERC20/extensions/ERC20VotesCompUpgradeable.sol"; +import "../proxy/utils/Initializable.sol"; + +contract ERC20VotesCompMockUpgradeable is Initializable, ERC20VotesCompUpgradeable { + function __ERC20VotesCompMock_init(string memory name, string memory symbol) public onlyInitializing { + __ERC20_init_unchained(name, symbol); + __EIP712_init_unchained(name, "1"); + __ERC20Permit_init_unchained(name); + } + + function __ERC20VotesCompMock_init_unchained(string memory, string memory) public onlyInitializing {} + + function mint(address account, uint256 amount) public { + _mint(account, amount); + } + + function burn(address account, uint256 amount) public { + _burn(account, amount); + } + + function getChainId() external view returns (uint256) { + return block.chainid; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[50] private __gap; +} diff --git a/contracts/mutants/ERC20VotesCompMockUpgradeable/2/MOI/ERC20VotesCompMockUpgradeable.sol b/contracts/mutants/ERC20VotesCompMockUpgradeable/2/MOI/ERC20VotesCompMockUpgradeable.sol new file mode 100644 index 00000000000..5747463581f --- /dev/null +++ b/contracts/mutants/ERC20VotesCompMockUpgradeable/2/MOI/ERC20VotesCompMockUpgradeable.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "../token/ERC20/extensions/ERC20VotesCompUpgradeable.sol"; +import "../proxy/utils/Initializable.sol"; + +contract ERC20VotesCompMockUpgradeable is Initializable, ERC20VotesCompUpgradeable { + function __ERC20VotesCompMock_init(string memory name, string memory symbol) internal onlyInitializing { + __ERC20_init_unchained(name, symbol); + __EIP712_init_unchained(name, "1"); + __ERC20Permit_init_unchained(name); + } + + function __ERC20VotesCompMock_init_unchained(string memory, string memory) internal onlyInitializing {} + + function mint(address account, uint256 amount) public onlyInitializing { + _mint(account, amount); + } + + function burn(address account, uint256 amount) public onlyInitializing { + _burn(account, amount); + } + + function getChainId() external view returns (uint256) { + return block.chainid; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[50] private __gap; +} diff --git a/contracts/mutants/ERC20VotesCompMockUpgradeable/3/DLR/ERC20VotesCompMockUpgradeable.sol b/contracts/mutants/ERC20VotesCompMockUpgradeable/3/DLR/ERC20VotesCompMockUpgradeable.sol new file mode 100644 index 00000000000..8a1ee1cdc95 --- /dev/null +++ b/contracts/mutants/ERC20VotesCompMockUpgradeable/3/DLR/ERC20VotesCompMockUpgradeable.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "../token/ERC20/extensions/ERC20VotesCompUpgradeable.sol"; +import "../proxy/utils/Initializable.sol"; + +contract ERC20VotesCompMockUpgradeable is Initializable, ERC20VotesCompUpgradeable { + function __ERC20VotesCompMock_init(string storage name, string storage symbol) internal onlyInitializing { + __ERC20_init_unchained(name, symbol); + __EIP712_init_unchained(name, "1"); + __ERC20Permit_init_unchained(name); + } + + function __ERC20VotesCompMock_init_unchained(string storage, string memory) internal onlyInitializing {} + + function mint(address account, uint256 amount) public { + _mint(account, amount); + } + + function burn(address account, uint256 amount) public { + _burn(account, amount); + } + + function getChainId() external view returns (uint256) { + return block.chainid; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[50] private __gap; +} diff --git a/contracts/mutants/ERC20VotesCompMockUpgradeable/3/FVR/ERC20VotesCompMockUpgradeable.sol b/contracts/mutants/ERC20VotesCompMockUpgradeable/3/FVR/ERC20VotesCompMockUpgradeable.sol new file mode 100644 index 00000000000..3e6ffce702c --- /dev/null +++ b/contracts/mutants/ERC20VotesCompMockUpgradeable/3/FVR/ERC20VotesCompMockUpgradeable.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "../token/ERC20/extensions/ERC20VotesCompUpgradeable.sol"; +import "../proxy/utils/Initializable.sol"; + +contract ERC20VotesCompMockUpgradeable is Initializable, ERC20VotesCompUpgradeable { + function __ERC20VotesCompMock_init(string memory name, string memory symbol) public onlyInitializing { + __ERC20_init_unchained(name, symbol); + __EIP712_init_unchained(name, "1"); + __ERC20Permit_init_unchained(name); + } + + function __ERC20VotesCompMock_init_unchained(string memory, string memory) public onlyInitializing {} + + function mint(address account, uint256 amount) external { + _mint(account, amount); + } + + function burn(address account, uint256 amount) public { + _burn(account, amount); + } + + function getChainId() external view returns (uint256) { + return block.chainid; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[50] private __gap; +} diff --git a/contracts/mutants/ERC20VotesCompMockUpgradeable/4/DLR/ERC20VotesCompMockUpgradeable.sol b/contracts/mutants/ERC20VotesCompMockUpgradeable/4/DLR/ERC20VotesCompMockUpgradeable.sol new file mode 100644 index 00000000000..5fad7432451 --- /dev/null +++ b/contracts/mutants/ERC20VotesCompMockUpgradeable/4/DLR/ERC20VotesCompMockUpgradeable.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "../token/ERC20/extensions/ERC20VotesCompUpgradeable.sol"; +import "../proxy/utils/Initializable.sol"; + +contract ERC20VotesCompMockUpgradeable is Initializable, ERC20VotesCompUpgradeable { + function __ERC20VotesCompMock_init(string storage name, string storage symbol) internal onlyInitializing { + __ERC20_init_unchained(name, symbol); + __EIP712_init_unchained(name, "1"); + __ERC20Permit_init_unchained(name); + } + + function __ERC20VotesCompMock_init_unchained(string storage, string storage) internal onlyInitializing {} + + function mint(address account, uint256 amount) public { + _mint(account, amount); + } + + function burn(address account, uint256 amount) public { + _burn(account, amount); + } + + function getChainId() external view returns (uint256) { + return block.chainid; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[50] private __gap; +} diff --git a/contracts/mutants/ERC20VotesCompMockUpgradeable/4/FVR/ERC20VotesCompMockUpgradeable.sol b/contracts/mutants/ERC20VotesCompMockUpgradeable/4/FVR/ERC20VotesCompMockUpgradeable.sol new file mode 100644 index 00000000000..311ec1fe6f1 --- /dev/null +++ b/contracts/mutants/ERC20VotesCompMockUpgradeable/4/FVR/ERC20VotesCompMockUpgradeable.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "../token/ERC20/extensions/ERC20VotesCompUpgradeable.sol"; +import "../proxy/utils/Initializable.sol"; + +contract ERC20VotesCompMockUpgradeable is Initializable, ERC20VotesCompUpgradeable { + function __ERC20VotesCompMock_init(string memory name, string memory symbol) public onlyInitializing { + __ERC20_init_unchained(name, symbol); + __EIP712_init_unchained(name, "1"); + __ERC20Permit_init_unchained(name); + } + + function __ERC20VotesCompMock_init_unchained(string memory, string memory) public onlyInitializing {} + + function mint(address account, uint256 amount) external { + _mint(account, amount); + } + + function burn(address account, uint256 amount) external { + _burn(account, amount); + } + + function getChainId() external view returns (uint256) { + return block.chainid; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[50] private __gap; +} diff --git a/contracts/mutants/ERC20VotesCompMockUpgradeable/5/FVR/ERC20VotesCompMockUpgradeable.sol b/contracts/mutants/ERC20VotesCompMockUpgradeable/5/FVR/ERC20VotesCompMockUpgradeable.sol new file mode 100644 index 00000000000..04a8c00429f --- /dev/null +++ b/contracts/mutants/ERC20VotesCompMockUpgradeable/5/FVR/ERC20VotesCompMockUpgradeable.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "../token/ERC20/extensions/ERC20VotesCompUpgradeable.sol"; +import "../proxy/utils/Initializable.sol"; + +contract ERC20VotesCompMockUpgradeable is Initializable, ERC20VotesCompUpgradeable { + function __ERC20VotesCompMock_init(string memory name, string memory symbol) public onlyInitializing { + __ERC20_init_unchained(name, symbol); + __EIP712_init_unchained(name, "1"); + __ERC20Permit_init_unchained(name); + } + + function __ERC20VotesCompMock_init_unchained(string memory, string memory) public onlyInitializing {} + + function mint(address account, uint256 amount) external { + _mint(account, amount); + } + + function burn(address account, uint256 amount) external { + _burn(account, amount); + } + + function getChainId() public view returns (uint256) { + return block.chainid; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[50] private __gap; +} diff --git a/contracts/mutants/ERC20VotesCompMockUpgradeable/original/ERC20VotesCompMockUpgradeable.sol b/contracts/mutants/ERC20VotesCompMockUpgradeable/original/ERC20VotesCompMockUpgradeable.sol new file mode 100644 index 00000000000..7e6e5c8dfc7 --- /dev/null +++ b/contracts/mutants/ERC20VotesCompMockUpgradeable/original/ERC20VotesCompMockUpgradeable.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "../token/ERC20/extensions/ERC20VotesCompUpgradeable.sol"; +import "../proxy/utils/Initializable.sol"; + +contract ERC20VotesCompMockUpgradeable is Initializable, ERC20VotesCompUpgradeable { + function __ERC20VotesCompMock_init(string memory name, string memory symbol) internal onlyInitializing { + __ERC20_init_unchained(name, symbol); + __EIP712_init_unchained(name, "1"); + __ERC20Permit_init_unchained(name); + } + + function __ERC20VotesCompMock_init_unchained(string memory, string memory) internal onlyInitializing {} + + function mint(address account, uint256 amount) public { + _mint(account, amount); + } + + function burn(address account, uint256 amount) public { + _burn(account, amount); + } + + function getChainId() external view returns (uint256) { + return block.chainid; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[50] private __gap; +} diff --git a/contracts/mutants/ERC20VotesCompUpgradeable/1/FVR/ERC20VotesCompUpgradeable.sol b/contracts/mutants/ERC20VotesCompUpgradeable/1/FVR/ERC20VotesCompUpgradeable.sol new file mode 100644 index 00000000000..7b02b9bb41a --- /dev/null +++ b/contracts/mutants/ERC20VotesCompUpgradeable/1/FVR/ERC20VotesCompUpgradeable.sol @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20VotesComp.sol) + +pragma solidity ^0.8.0; + +import "./ERC20VotesUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound's voting and delegation. This version exactly matches Compound's + * interface, with the drawback of only supporting supply up to (2^96^ - 1). + * + * NOTE: You should use this contract if you need exact compatibility with COMP (for example in order to use your token + * with Governor Alpha or Bravo) and if you are sure the supply cap of 2^96^ is enough for you. Otherwise, use the + * {ERC20Votes} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getCurrentVotes} and {getPriorVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesCompUpgradeable is Initializable, ERC20VotesUpgradeable { + function __ERC20VotesComp_init() public onlyInitializing { + } + + function __ERC20VotesComp_init_unchained() internal onlyInitializing { + } + /** + * @dev Comp version of the {getVotes} accessor, with `uint96` return type. + */ + function getCurrentVotes(address account) external view virtual returns (uint96) { + return SafeCastUpgradeable.toUint96(getVotes(account)); + } + + /** + * @dev Comp version of the {getPastVotes} accessor, with `uint96` return type. + */ + function getPriorVotes(address account, uint256 blockNumber) external view virtual returns (uint96) { + return SafeCastUpgradeable.toUint96(getPastVotes(account, blockNumber)); + } + + /** + * @dev Maximum token supply. Reduced to `type(uint96).max` (2^96^ - 1) to fit COMP interface. + */ + function _maxSupply() internal view virtual override returns (uint224) { + return type(uint96).max; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[50] private __gap; +} diff --git a/contracts/mutants/ERC20VotesCompUpgradeable/1/ILR/ERC20VotesCompUpgradeable.sol b/contracts/mutants/ERC20VotesCompUpgradeable/1/ILR/ERC20VotesCompUpgradeable.sol new file mode 100644 index 00000000000..2f8225fec7f --- /dev/null +++ b/contracts/mutants/ERC20VotesCompUpgradeable/1/ILR/ERC20VotesCompUpgradeable.sol @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20VotesComp.sol) + +pragma solidity ^0.8.0; + +import "./ERC20VotesUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound's voting and delegation. This version exactly matches Compound's + * interface, with the drawback of only supporting supply up to (2^96^ - 1). + * + * NOTE: You should use this contract if you need exact compatibility with COMP (for example in order to use your token + * with Governor Alpha or Bravo) and if you are sure the supply cap of 2^96^ is enough for you. Otherwise, use the + * {ERC20Votes} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getCurrentVotes} and {getPriorVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesCompUpgradeable is Initializable, ERC20VotesUpgradeable { + function __ERC20VotesComp_init() internal onlyInitializing { + } + + function __ERC20VotesComp_init_unchained() internal onlyInitializing { + } + /** + * @dev Comp version of the {getVotes} accessor, with `uint96` return type. + */ + function getCurrentVotes(address account) external view virtual returns (uint96) { + return SafeCastUpgradeable.toUint96(getVotes(account)); + } + + /** + * @dev Comp version of the {getPastVotes} accessor, with `uint96` return type. + */ + function getPriorVotes(address account, uint256 blockNumber) external view virtual returns (uint96) { + return SafeCastUpgradeable.toUint96(getPastVotes(account, blockNumber)); + } + + /** + * @dev Maximum token supply. Reduced to `type(uint96).max` (2^96^ - 1) to fit COMP interface. + */ + function _maxSupply() internal view virtual override returns (uint224) { + return type(uint96).max; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[49] private __gap; +} diff --git a/contracts/mutants/ERC20VotesCompUpgradeable/1/ORFD/ERC20VotesCompUpgradeable.sol b/contracts/mutants/ERC20VotesCompUpgradeable/1/ORFD/ERC20VotesCompUpgradeable.sol new file mode 100644 index 00000000000..2877c2de983 --- /dev/null +++ b/contracts/mutants/ERC20VotesCompUpgradeable/1/ORFD/ERC20VotesCompUpgradeable.sol @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20VotesComp.sol) + +pragma solidity ^0.8.0; + +import "./ERC20VotesUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound's voting and delegation. This version exactly matches Compound's + * interface, with the drawback of only supporting supply up to (2^96^ - 1). + * + * NOTE: You should use this contract if you need exact compatibility with COMP (for example in order to use your token + * with Governor Alpha or Bravo) and if you are sure the supply cap of 2^96^ is enough for you. Otherwise, use the + * {ERC20Votes} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getCurrentVotes} and {getPriorVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesCompUpgradeable is Initializable, ERC20VotesUpgradeable { + function __ERC20VotesComp_init() internal onlyInitializing { + } + + function __ERC20VotesComp_init_unchained() internal onlyInitializing { + } + /** + * @dev Comp version of the {getVotes} accessor, with `uint96` return type. + */ + function getCurrentVotes(address account) external view virtual returns (uint96) { + return SafeCastUpgradeable.toUint96(getVotes(account)); + } + + /** + * @dev Comp version of the {getPastVotes} accessor, with `uint96` return type. + */ + function getPriorVotes(address account, uint256 blockNumber) external view virtual returns (uint96) { + return SafeCastUpgradeable.toUint96(getPastVotes(account, blockNumber)); + } + + /** + * @dev Maximum token supply. Reduced to `type(uint96).max` (2^96^ - 1) to fit COMP interface. + */ + + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[50] private __gap; +} diff --git a/contracts/mutants/ERC20VotesCompUpgradeable/1/RSD/ERC20VotesCompUpgradeable.sol b/contracts/mutants/ERC20VotesCompUpgradeable/1/RSD/ERC20VotesCompUpgradeable.sol new file mode 100644 index 00000000000..4c6dfa206d1 --- /dev/null +++ b/contracts/mutants/ERC20VotesCompUpgradeable/1/RSD/ERC20VotesCompUpgradeable.sol @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20VotesComp.sol) + +pragma solidity ^0.8.0; + +import "./ERC20VotesUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound's voting and delegation. This version exactly matches Compound's + * interface, with the drawback of only supporting supply up to (2^96^ - 1). + * + * NOTE: You should use this contract if you need exact compatibility with COMP (for example in order to use your token + * with Governor Alpha or Bravo) and if you are sure the supply cap of 2^96^ is enough for you. Otherwise, use the + * {ERC20Votes} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getCurrentVotes} and {getPriorVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesCompUpgradeable is Initializable, ERC20VotesUpgradeable { + function __ERC20VotesComp_init() internal onlyInitializing { + } + + function __ERC20VotesComp_init_unchained() internal onlyInitializing { + } + /** + * @dev Comp version of the {getVotes} accessor, with `uint96` return type. + */ + function getCurrentVotes(address account) external view virtual returns (uint96) { + /* return SafeCastUpgradeable.toUint96(getVotes(account)); */ + } + + /** + * @dev Comp version of the {getPastVotes} accessor, with `uint96` return type. + */ + function getPriorVotes(address account, uint256 blockNumber) external view virtual returns (uint96) { + return SafeCastUpgradeable.toUint96(getPastVotes(account, blockNumber)); + } + + /** + * @dev Maximum token supply. Reduced to `type(uint96).max` (2^96^ - 1) to fit COMP interface. + */ + function _maxSupply() internal view virtual override returns (uint224) { + return type(uint96).max; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[50] private __gap; +} diff --git a/contracts/mutants/ERC20VotesCompUpgradeable/1/VVR/ERC20VotesCompUpgradeable.sol b/contracts/mutants/ERC20VotesCompUpgradeable/1/VVR/ERC20VotesCompUpgradeable.sol new file mode 100644 index 00000000000..993a77cd5b5 --- /dev/null +++ b/contracts/mutants/ERC20VotesCompUpgradeable/1/VVR/ERC20VotesCompUpgradeable.sol @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20VotesComp.sol) + +pragma solidity ^0.8.0; + +import "./ERC20VotesUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound's voting and delegation. This version exactly matches Compound's + * interface, with the drawback of only supporting supply up to (2^96^ - 1). + * + * NOTE: You should use this contract if you need exact compatibility with COMP (for example in order to use your token + * with Governor Alpha or Bravo) and if you are sure the supply cap of 2^96^ is enough for you. Otherwise, use the + * {ERC20Votes} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getCurrentVotes} and {getPriorVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesCompUpgradeable is Initializable, ERC20VotesUpgradeable { + function __ERC20VotesComp_init() internal onlyInitializing { + } + + function __ERC20VotesComp_init_unchained() internal onlyInitializing { + } + /** + * @dev Comp version of the {getVotes} accessor, with `uint96` return type. + */ + function getCurrentVotes(address account) external view virtual returns (uint96) { + return SafeCastUpgradeable.toUint96(getVotes(account)); + } + + /** + * @dev Comp version of the {getPastVotes} accessor, with `uint96` return type. + */ + function getPriorVotes(address account, uint256 blockNumber) external view virtual returns (uint96) { + return SafeCastUpgradeable.toUint96(getPastVotes(account, blockNumber)); + } + + /** + * @dev Maximum token supply. Reduced to `type(uint96).max` (2^96^ - 1) to fit COMP interface. + */ + function _maxSupply() internal view virtual override returns (uint224) { + return type(uint96).max; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[50] public __gap; +} diff --git a/contracts/mutants/ERC20VotesCompUpgradeable/2/FVR/ERC20VotesCompUpgradeable.sol b/contracts/mutants/ERC20VotesCompUpgradeable/2/FVR/ERC20VotesCompUpgradeable.sol new file mode 100644 index 00000000000..1b3bb5af3af --- /dev/null +++ b/contracts/mutants/ERC20VotesCompUpgradeable/2/FVR/ERC20VotesCompUpgradeable.sol @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20VotesComp.sol) + +pragma solidity ^0.8.0; + +import "./ERC20VotesUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound's voting and delegation. This version exactly matches Compound's + * interface, with the drawback of only supporting supply up to (2^96^ - 1). + * + * NOTE: You should use this contract if you need exact compatibility with COMP (for example in order to use your token + * with Governor Alpha or Bravo) and if you are sure the supply cap of 2^96^ is enough for you. Otherwise, use the + * {ERC20Votes} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getCurrentVotes} and {getPriorVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesCompUpgradeable is Initializable, ERC20VotesUpgradeable { + function __ERC20VotesComp_init() public onlyInitializing { + } + + function __ERC20VotesComp_init_unchained() public onlyInitializing { + } + /** + * @dev Comp version of the {getVotes} accessor, with `uint96` return type. + */ + function getCurrentVotes(address account) external view virtual returns (uint96) { + return SafeCastUpgradeable.toUint96(getVotes(account)); + } + + /** + * @dev Comp version of the {getPastVotes} accessor, with `uint96` return type. + */ + function getPriorVotes(address account, uint256 blockNumber) external view virtual returns (uint96) { + return SafeCastUpgradeable.toUint96(getPastVotes(account, blockNumber)); + } + + /** + * @dev Maximum token supply. Reduced to `type(uint96).max` (2^96^ - 1) to fit COMP interface. + */ + function _maxSupply() internal view virtual override returns (uint224) { + return type(uint96).max; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[50] private __gap; +} diff --git a/contracts/mutants/ERC20VotesCompUpgradeable/2/RSD/ERC20VotesCompUpgradeable.sol b/contracts/mutants/ERC20VotesCompUpgradeable/2/RSD/ERC20VotesCompUpgradeable.sol new file mode 100644 index 00000000000..3be2801c4ae --- /dev/null +++ b/contracts/mutants/ERC20VotesCompUpgradeable/2/RSD/ERC20VotesCompUpgradeable.sol @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20VotesComp.sol) + +pragma solidity ^0.8.0; + +import "./ERC20VotesUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound's voting and delegation. This version exactly matches Compound's + * interface, with the drawback of only supporting supply up to (2^96^ - 1). + * + * NOTE: You should use this contract if you need exact compatibility with COMP (for example in order to use your token + * with Governor Alpha or Bravo) and if you are sure the supply cap of 2^96^ is enough for you. Otherwise, use the + * {ERC20Votes} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getCurrentVotes} and {getPriorVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesCompUpgradeable is Initializable, ERC20VotesUpgradeable { + function __ERC20VotesComp_init() internal onlyInitializing { + } + + function __ERC20VotesComp_init_unchained() internal onlyInitializing { + } + /** + * @dev Comp version of the {getVotes} accessor, with `uint96` return type. + */ + function getCurrentVotes(address account) external view virtual returns (uint96) { + /* return SafeCastUpgradeable.toUint96(getVotes(account)); */ + } + + /** + * @dev Comp version of the {getPastVotes} accessor, with `uint96` return type. + */ + function getPriorVotes(address account, uint256 blockNumber) external view virtual returns (uint96) { + /* return SafeCastUpgradeable.toUint96(getPastVotes(account, blockNumber)); */ + } + + /** + * @dev Maximum token supply. Reduced to `type(uint96).max` (2^96^ - 1) to fit COMP interface. + */ + function _maxSupply() internal view virtual override returns (uint224) { + return type(uint96).max; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[50] private __gap; +} diff --git a/contracts/mutants/ERC20VotesCompUpgradeable/3/RSD/ERC20VotesCompUpgradeable.sol b/contracts/mutants/ERC20VotesCompUpgradeable/3/RSD/ERC20VotesCompUpgradeable.sol new file mode 100644 index 00000000000..f671e95588a --- /dev/null +++ b/contracts/mutants/ERC20VotesCompUpgradeable/3/RSD/ERC20VotesCompUpgradeable.sol @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20VotesComp.sol) + +pragma solidity ^0.8.0; + +import "./ERC20VotesUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound's voting and delegation. This version exactly matches Compound's + * interface, with the drawback of only supporting supply up to (2^96^ - 1). + * + * NOTE: You should use this contract if you need exact compatibility with COMP (for example in order to use your token + * with Governor Alpha or Bravo) and if you are sure the supply cap of 2^96^ is enough for you. Otherwise, use the + * {ERC20Votes} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getCurrentVotes} and {getPriorVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesCompUpgradeable is Initializable, ERC20VotesUpgradeable { + function __ERC20VotesComp_init() internal onlyInitializing { + } + + function __ERC20VotesComp_init_unchained() internal onlyInitializing { + } + /** + * @dev Comp version of the {getVotes} accessor, with `uint96` return type. + */ + function getCurrentVotes(address account) external view virtual returns (uint96) { + /* return SafeCastUpgradeable.toUint96(getVotes(account)); */ + } + + /** + * @dev Comp version of the {getPastVotes} accessor, with `uint96` return type. + */ + function getPriorVotes(address account, uint256 blockNumber) external view virtual returns (uint96) { + /* return SafeCastUpgradeable.toUint96(getPastVotes(account, blockNumber)); */ + } + + /** + * @dev Maximum token supply. Reduced to `type(uint96).max` (2^96^ - 1) to fit COMP interface. + */ + function _maxSupply() internal view virtual override returns (uint224) { + /* return type(uint96).max; */ + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[50] private __gap; +} diff --git a/contracts/mutants/ERC20VotesCompUpgradeable/original/ERC20VotesCompUpgradeable.sol b/contracts/mutants/ERC20VotesCompUpgradeable/original/ERC20VotesCompUpgradeable.sol new file mode 100644 index 00000000000..5a6eb2a1301 --- /dev/null +++ b/contracts/mutants/ERC20VotesCompUpgradeable/original/ERC20VotesCompUpgradeable.sol @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20VotesComp.sol) + +pragma solidity ^0.8.0; + +import "./ERC20VotesUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound's voting and delegation. This version exactly matches Compound's + * interface, with the drawback of only supporting supply up to (2^96^ - 1). + * + * NOTE: You should use this contract if you need exact compatibility with COMP (for example in order to use your token + * with Governor Alpha or Bravo) and if you are sure the supply cap of 2^96^ is enough for you. Otherwise, use the + * {ERC20Votes} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getCurrentVotes} and {getPriorVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesCompUpgradeable is Initializable, ERC20VotesUpgradeable { + function __ERC20VotesComp_init() internal onlyInitializing { + } + + function __ERC20VotesComp_init_unchained() internal onlyInitializing { + } + /** + * @dev Comp version of the {getVotes} accessor, with `uint96` return type. + */ + function getCurrentVotes(address account) external view virtual returns (uint96) { + return SafeCastUpgradeable.toUint96(getVotes(account)); + } + + /** + * @dev Comp version of the {getPastVotes} accessor, with `uint96` return type. + */ + function getPriorVotes(address account, uint256 blockNumber) external view virtual returns (uint96) { + return SafeCastUpgradeable.toUint96(getPastVotes(account, blockNumber)); + } + + /** + * @dev Maximum token supply. Reduced to `type(uint96).max` (2^96^ - 1) to fit COMP interface. + */ + function _maxSupply() internal view virtual override returns (uint224) { + return type(uint96).max; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[50] private __gap; +} diff --git a/contracts/mutants/ERC20VotesHarness/1/AOR/ERC20VotesHarness.sol b/contracts/mutants/ERC20VotesHarness/1/AOR/ERC20VotesHarness.sol new file mode 100644 index 00000000000..f1b7cdbfa5f --- /dev/null +++ b/contracts/mutants/ERC20VotesHarness/1/AOR/ERC20VotesHarness.sol @@ -0,0 +1,28 @@ +import "../munged/token/ERC20/extensions/ERC20Votes.sol"; + +contract ERC20VotesHarness is ERC20Votes { + constructor(string memory name, string memory symbol) ERC20Permit(name) ERC20(name, symbol) {} + + mapping(address => mapping(uint256 => uint256)) public _getPastVotes; + + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + _getPastVotes[from][block.number] += amount; + _getPastVotes[to][block.number] += amount; + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual override{ + super._delegate(delegator, delegatee); + _getPastVotes[delegator][block.number] -= balanceOf(delegator); + _getPastVotes[delegatee][block.number] += balanceOf(delegator); + } +} diff --git a/contracts/mutants/ERC20VotesHarness/1/AVR/ERC20VotesHarness.sol b/contracts/mutants/ERC20VotesHarness/1/AVR/ERC20VotesHarness.sol new file mode 100644 index 00000000000..f1b7cdbfa5f --- /dev/null +++ b/contracts/mutants/ERC20VotesHarness/1/AVR/ERC20VotesHarness.sol @@ -0,0 +1,28 @@ +import "../munged/token/ERC20/extensions/ERC20Votes.sol"; + +contract ERC20VotesHarness is ERC20Votes { + constructor(string memory name, string memory symbol) ERC20Permit(name) ERC20(name, symbol) {} + + mapping(address => mapping(uint256 => uint256)) public _getPastVotes; + + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + _getPastVotes[from][block.number] += amount; + _getPastVotes[to][block.number] += amount; + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual override{ + super._delegate(delegator, delegatee); + _getPastVotes[delegator][block.number] -= balanceOf(delegator); + _getPastVotes[delegatee][block.number] += balanceOf(delegator); + } +} diff --git a/contracts/mutants/ERC20VotesHarness/1/CCD/ERC20VotesHarness.sol b/contracts/mutants/ERC20VotesHarness/1/CCD/ERC20VotesHarness.sol new file mode 100644 index 00000000000..c9a26fb87b6 --- /dev/null +++ b/contracts/mutants/ERC20VotesHarness/1/CCD/ERC20VotesHarness.sol @@ -0,0 +1,28 @@ +import "../munged/token/ERC20/extensions/ERC20Votes.sol"; + +contract ERC20VotesHarness is ERC20Votes { + + + mapping(address => mapping(uint256 => uint256)) public _getPastVotes; + + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + _getPastVotes[from][block.number] -= amount; + _getPastVotes[to][block.number] += amount; + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual override{ + super._delegate(delegator, delegatee); + _getPastVotes[delegator][block.number] -= balanceOf(delegator); + _getPastVotes[delegatee][block.number] += balanceOf(delegator); + } +} diff --git a/contracts/mutants/ERC20VotesHarness/1/DLR/ERC20VotesHarness.sol b/contracts/mutants/ERC20VotesHarness/1/DLR/ERC20VotesHarness.sol new file mode 100644 index 00000000000..6aaedb392f8 --- /dev/null +++ b/contracts/mutants/ERC20VotesHarness/1/DLR/ERC20VotesHarness.sol @@ -0,0 +1,28 @@ +import "../munged/token/ERC20/extensions/ERC20Votes.sol"; + +contract ERC20VotesHarness is ERC20Votes { + constructor(string storage name, string memory symbol) ERC20Permit(name) ERC20(name, symbol) {} + + mapping(address => mapping(uint256 => uint256)) public _getPastVotes; + + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + _getPastVotes[from][block.number] -= amount; + _getPastVotes[to][block.number] += amount; + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual override{ + super._delegate(delegator, delegatee); + _getPastVotes[delegator][block.number] -= balanceOf(delegator); + _getPastVotes[delegatee][block.number] += balanceOf(delegator); + } +} diff --git a/contracts/mutants/ERC20VotesHarness/1/GVR/ERC20VotesHarness.sol b/contracts/mutants/ERC20VotesHarness/1/GVR/ERC20VotesHarness.sol new file mode 100644 index 00000000000..225254ff249 --- /dev/null +++ b/contracts/mutants/ERC20VotesHarness/1/GVR/ERC20VotesHarness.sol @@ -0,0 +1,28 @@ +import "../munged/token/ERC20/extensions/ERC20Votes.sol"; + +contract ERC20VotesHarness is ERC20Votes { + constructor(string memory name, string memory symbol) ERC20Permit(name) ERC20(name, symbol) {} + + mapping(address => mapping(uint256 => uint256)) public _getPastVotes; + + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + _getPastVotes[from][block.difficulty] -= amount; + _getPastVotes[to][block.number] += amount; + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual override{ + super._delegate(delegator, delegatee); + _getPastVotes[delegator][block.number] -= balanceOf(delegator); + _getPastVotes[delegatee][block.number] += balanceOf(delegator); + } +} diff --git a/contracts/mutants/ERC20VotesHarness/1/ICM/ERC20VotesHarness.sol b/contracts/mutants/ERC20VotesHarness/1/ICM/ERC20VotesHarness.sol new file mode 100644 index 00000000000..353a03adea8 --- /dev/null +++ b/contracts/mutants/ERC20VotesHarness/1/ICM/ERC20VotesHarness.sol @@ -0,0 +1,28 @@ +import "../munged/token/ERC20/extensions/ERC20Votes.sol"; + +contract ERC20VotesHarness is ERC20Votes { + constructor(string memory name, string memory symbol) ERC20Permit(name) ERC20(name, symbol) {} + + mapping(address => mapping(uint256 => uint256)) public _getPastVotes; + + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + _getPastVotes[from][block.number] =- amount; + _getPastVotes[to][block.number] += amount; + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual override{ + super._delegate(delegator, delegatee); + _getPastVotes[delegator][block.number] -= balanceOf(delegator); + _getPastVotes[delegatee][block.number] += balanceOf(delegator); + } +} diff --git a/contracts/mutants/ERC20VotesHarness/1/MOC/ERC20VotesHarness.sol b/contracts/mutants/ERC20VotesHarness/1/MOC/ERC20VotesHarness.sol new file mode 100644 index 00000000000..43fb5c596ac --- /dev/null +++ b/contracts/mutants/ERC20VotesHarness/1/MOC/ERC20VotesHarness.sol @@ -0,0 +1,28 @@ +import "../munged/token/ERC20/extensions/ERC20Votes.sol"; + +contract ERC20VotesHarness is ERC20Votes { + constructor(string memory name, string memory symbol) ERC20(name, symbol) ERC20Permit(name) {} + + mapping(address => mapping(uint256 => uint256)) public _getPastVotes; + + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + _getPastVotes[from][block.number] -= amount; + _getPastVotes[to][block.number] += amount; + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual override{ + super._delegate(delegator, delegatee); + _getPastVotes[delegator][block.number] -= balanceOf(delegator); + _getPastVotes[delegatee][block.number] += balanceOf(delegator); + } +} diff --git a/contracts/mutants/ERC20VotesHarness/1/MOD/ERC20VotesHarness.sol b/contracts/mutants/ERC20VotesHarness/1/MOD/ERC20VotesHarness.sol new file mode 100644 index 00000000000..0a203858812 --- /dev/null +++ b/contracts/mutants/ERC20VotesHarness/1/MOD/ERC20VotesHarness.sol @@ -0,0 +1,28 @@ +import "../munged/token/ERC20/extensions/ERC20Votes.sol"; + +contract ERC20VotesHarness is ERC20Votes { + constructor(string memory name, string memory symbol) ERC20(name, symbol) {} + + mapping(address => mapping(uint256 => uint256)) public _getPastVotes; + + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + _getPastVotes[from][block.number] -= amount; + _getPastVotes[to][block.number] += amount; + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual override{ + super._delegate(delegator, delegatee); + _getPastVotes[delegator][block.number] -= balanceOf(delegator); + _getPastVotes[delegatee][block.number] += balanceOf(delegator); + } +} diff --git a/contracts/mutants/ERC20VotesHarness/1/ORFD/ERC20VotesHarness.sol b/contracts/mutants/ERC20VotesHarness/1/ORFD/ERC20VotesHarness.sol new file mode 100644 index 00000000000..cd7f73cf15a --- /dev/null +++ b/contracts/mutants/ERC20VotesHarness/1/ORFD/ERC20VotesHarness.sol @@ -0,0 +1,20 @@ +import "../munged/token/ERC20/extensions/ERC20Votes.sol"; + +contract ERC20VotesHarness is ERC20Votes { + constructor(string memory name, string memory symbol) ERC20Permit(name) ERC20(name, symbol) {} + + mapping(address => mapping(uint256 => uint256)) public _getPastVotes; + + + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual override{ + super._delegate(delegator, delegatee); + _getPastVotes[delegator][block.number] -= balanceOf(delegator); + _getPastVotes[delegatee][block.number] += balanceOf(delegator); + } +} diff --git a/contracts/mutants/ERC20VotesHarness/1/SKD/ERC20VotesHarness.sol b/contracts/mutants/ERC20VotesHarness/1/SKD/ERC20VotesHarness.sol new file mode 100644 index 00000000000..637099b9921 --- /dev/null +++ b/contracts/mutants/ERC20VotesHarness/1/SKD/ERC20VotesHarness.sol @@ -0,0 +1,28 @@ +import "../munged/token/ERC20/extensions/ERC20Votes.sol"; + +contract ERC20VotesHarness is ERC20Votes { + constructor(string memory name, string memory symbol) ERC20Permit(name) ERC20(name, symbol) {} + + mapping(address => mapping(uint256 => uint256)) public _getPastVotes; + + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + _afterTokenTransfer(from, to, amount); + _getPastVotes[from][block.number] -= amount; + _getPastVotes[to][block.number] += amount; + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual override{ + super._delegate(delegator, delegatee); + _getPastVotes[delegator][block.number] -= balanceOf(delegator); + _getPastVotes[delegatee][block.number] += balanceOf(delegator); + } +} diff --git a/contracts/mutants/ERC20VotesHarness/2/AOR/ERC20VotesHarness.sol b/contracts/mutants/ERC20VotesHarness/2/AOR/ERC20VotesHarness.sol new file mode 100644 index 00000000000..8f4aa072f2b --- /dev/null +++ b/contracts/mutants/ERC20VotesHarness/2/AOR/ERC20VotesHarness.sol @@ -0,0 +1,28 @@ +import "../munged/token/ERC20/extensions/ERC20Votes.sol"; + +contract ERC20VotesHarness is ERC20Votes { + constructor(string memory name, string memory symbol) ERC20Permit(name) ERC20(name, symbol) {} + + mapping(address => mapping(uint256 => uint256)) public _getPastVotes; + + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + _getPastVotes[from][block.number] += amount; + _getPastVotes[to][block.number] -= amount; + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual override{ + super._delegate(delegator, delegatee); + _getPastVotes[delegator][block.number] -= balanceOf(delegator); + _getPastVotes[delegatee][block.number] += balanceOf(delegator); + } +} diff --git a/contracts/mutants/ERC20VotesHarness/2/AVR/ERC20VotesHarness.sol b/contracts/mutants/ERC20VotesHarness/2/AVR/ERC20VotesHarness.sol new file mode 100644 index 00000000000..8f4aa072f2b --- /dev/null +++ b/contracts/mutants/ERC20VotesHarness/2/AVR/ERC20VotesHarness.sol @@ -0,0 +1,28 @@ +import "../munged/token/ERC20/extensions/ERC20Votes.sol"; + +contract ERC20VotesHarness is ERC20Votes { + constructor(string memory name, string memory symbol) ERC20Permit(name) ERC20(name, symbol) {} + + mapping(address => mapping(uint256 => uint256)) public _getPastVotes; + + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + _getPastVotes[from][block.number] += amount; + _getPastVotes[to][block.number] -= amount; + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual override{ + super._delegate(delegator, delegatee); + _getPastVotes[delegator][block.number] -= balanceOf(delegator); + _getPastVotes[delegatee][block.number] += balanceOf(delegator); + } +} diff --git a/contracts/mutants/ERC20VotesHarness/2/DLR/ERC20VotesHarness.sol b/contracts/mutants/ERC20VotesHarness/2/DLR/ERC20VotesHarness.sol new file mode 100644 index 00000000000..ee2fce7e833 --- /dev/null +++ b/contracts/mutants/ERC20VotesHarness/2/DLR/ERC20VotesHarness.sol @@ -0,0 +1,28 @@ +import "../munged/token/ERC20/extensions/ERC20Votes.sol"; + +contract ERC20VotesHarness is ERC20Votes { + constructor(string storage name, string storage symbol) ERC20Permit(name) ERC20(name, symbol) {} + + mapping(address => mapping(uint256 => uint256)) public _getPastVotes; + + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + _getPastVotes[from][block.number] -= amount; + _getPastVotes[to][block.number] += amount; + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual override{ + super._delegate(delegator, delegatee); + _getPastVotes[delegator][block.number] -= balanceOf(delegator); + _getPastVotes[delegatee][block.number] += balanceOf(delegator); + } +} diff --git a/contracts/mutants/ERC20VotesHarness/2/GVR/ERC20VotesHarness.sol b/contracts/mutants/ERC20VotesHarness/2/GVR/ERC20VotesHarness.sol new file mode 100644 index 00000000000..32ed678d66d --- /dev/null +++ b/contracts/mutants/ERC20VotesHarness/2/GVR/ERC20VotesHarness.sol @@ -0,0 +1,28 @@ +import "../munged/token/ERC20/extensions/ERC20Votes.sol"; + +contract ERC20VotesHarness is ERC20Votes { + constructor(string memory name, string memory symbol) ERC20Permit(name) ERC20(name, symbol) {} + + mapping(address => mapping(uint256 => uint256)) public _getPastVotes; + + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + _getPastVotes[from][block.difficulty] -= amount; + _getPastVotes[to][block.difficulty] += amount; + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual override{ + super._delegate(delegator, delegatee); + _getPastVotes[delegator][block.number] -= balanceOf(delegator); + _getPastVotes[delegatee][block.number] += balanceOf(delegator); + } +} diff --git a/contracts/mutants/ERC20VotesHarness/2/ICM/ERC20VotesHarness.sol b/contracts/mutants/ERC20VotesHarness/2/ICM/ERC20VotesHarness.sol new file mode 100644 index 00000000000..14ffbcc2e1c --- /dev/null +++ b/contracts/mutants/ERC20VotesHarness/2/ICM/ERC20VotesHarness.sol @@ -0,0 +1,28 @@ +import "../munged/token/ERC20/extensions/ERC20Votes.sol"; + +contract ERC20VotesHarness is ERC20Votes { + constructor(string memory name, string memory symbol) ERC20Permit(name) ERC20(name, symbol) {} + + mapping(address => mapping(uint256 => uint256)) public _getPastVotes; + + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + _getPastVotes[from][block.number] =- amount; + _getPastVotes[to][block.number] += amount; + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual override{ + super._delegate(delegator, delegatee); + _getPastVotes[delegator][block.number] =- balanceOf(delegator); + _getPastVotes[delegatee][block.number] += balanceOf(delegator); + } +} diff --git a/contracts/mutants/ERC20VotesHarness/2/ORFD/ERC20VotesHarness.sol b/contracts/mutants/ERC20VotesHarness/2/ORFD/ERC20VotesHarness.sol new file mode 100644 index 00000000000..bfc02a85b86 --- /dev/null +++ b/contracts/mutants/ERC20VotesHarness/2/ORFD/ERC20VotesHarness.sol @@ -0,0 +1,16 @@ +import "../munged/token/ERC20/extensions/ERC20Votes.sol"; + +contract ERC20VotesHarness is ERC20Votes { + constructor(string memory name, string memory symbol) ERC20Permit(name) ERC20(name, symbol) {} + + mapping(address => mapping(uint256 => uint256)) public _getPastVotes; + + + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + +} diff --git a/contracts/mutants/ERC20VotesHarness/2/SKD/ERC20VotesHarness.sol b/contracts/mutants/ERC20VotesHarness/2/SKD/ERC20VotesHarness.sol new file mode 100644 index 00000000000..bd45cf05a01 --- /dev/null +++ b/contracts/mutants/ERC20VotesHarness/2/SKD/ERC20VotesHarness.sol @@ -0,0 +1,28 @@ +import "../munged/token/ERC20/extensions/ERC20Votes.sol"; + +contract ERC20VotesHarness is ERC20Votes { + constructor(string memory name, string memory symbol) ERC20Permit(name) ERC20(name, symbol) {} + + mapping(address => mapping(uint256 => uint256)) public _getPastVotes; + + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + _afterTokenTransfer(from, to, amount); + _getPastVotes[from][block.number] -= amount; + _getPastVotes[to][block.number] += amount; + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual override{ + _delegate(delegator, delegatee); + _getPastVotes[delegator][block.number] -= balanceOf(delegator); + _getPastVotes[delegatee][block.number] += balanceOf(delegator); + } +} diff --git a/contracts/mutants/ERC20VotesHarness/3/AOR/ERC20VotesHarness.sol b/contracts/mutants/ERC20VotesHarness/3/AOR/ERC20VotesHarness.sol new file mode 100644 index 00000000000..2244c9f1285 --- /dev/null +++ b/contracts/mutants/ERC20VotesHarness/3/AOR/ERC20VotesHarness.sol @@ -0,0 +1,28 @@ +import "../munged/token/ERC20/extensions/ERC20Votes.sol"; + +contract ERC20VotesHarness is ERC20Votes { + constructor(string memory name, string memory symbol) ERC20Permit(name) ERC20(name, symbol) {} + + mapping(address => mapping(uint256 => uint256)) public _getPastVotes; + + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + _getPastVotes[from][block.number] += amount; + _getPastVotes[to][block.number] -= amount; + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual override{ + super._delegate(delegator, delegatee); + _getPastVotes[delegator][block.number] += balanceOf(delegator); + _getPastVotes[delegatee][block.number] += balanceOf(delegator); + } +} diff --git a/contracts/mutants/ERC20VotesHarness/3/AVR/ERC20VotesHarness.sol b/contracts/mutants/ERC20VotesHarness/3/AVR/ERC20VotesHarness.sol new file mode 100644 index 00000000000..2244c9f1285 --- /dev/null +++ b/contracts/mutants/ERC20VotesHarness/3/AVR/ERC20VotesHarness.sol @@ -0,0 +1,28 @@ +import "../munged/token/ERC20/extensions/ERC20Votes.sol"; + +contract ERC20VotesHarness is ERC20Votes { + constructor(string memory name, string memory symbol) ERC20Permit(name) ERC20(name, symbol) {} + + mapping(address => mapping(uint256 => uint256)) public _getPastVotes; + + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + _getPastVotes[from][block.number] += amount; + _getPastVotes[to][block.number] -= amount; + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual override{ + super._delegate(delegator, delegatee); + _getPastVotes[delegator][block.number] += balanceOf(delegator); + _getPastVotes[delegatee][block.number] += balanceOf(delegator); + } +} diff --git a/contracts/mutants/ERC20VotesHarness/3/GVR/ERC20VotesHarness.sol b/contracts/mutants/ERC20VotesHarness/3/GVR/ERC20VotesHarness.sol new file mode 100644 index 00000000000..042fb8cd604 --- /dev/null +++ b/contracts/mutants/ERC20VotesHarness/3/GVR/ERC20VotesHarness.sol @@ -0,0 +1,28 @@ +import "../munged/token/ERC20/extensions/ERC20Votes.sol"; + +contract ERC20VotesHarness is ERC20Votes { + constructor(string memory name, string memory symbol) ERC20Permit(name) ERC20(name, symbol) {} + + mapping(address => mapping(uint256 => uint256)) public _getPastVotes; + + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + _getPastVotes[from][block.difficulty] -= amount; + _getPastVotes[to][block.difficulty] += amount; + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual override{ + super._delegate(delegator, delegatee); + _getPastVotes[delegator][block.difficulty] -= balanceOf(delegator); + _getPastVotes[delegatee][block.number] += balanceOf(delegator); + } +} diff --git a/contracts/mutants/ERC20VotesHarness/4/AOR/ERC20VotesHarness.sol b/contracts/mutants/ERC20VotesHarness/4/AOR/ERC20VotesHarness.sol new file mode 100644 index 00000000000..22aca924252 --- /dev/null +++ b/contracts/mutants/ERC20VotesHarness/4/AOR/ERC20VotesHarness.sol @@ -0,0 +1,28 @@ +import "../munged/token/ERC20/extensions/ERC20Votes.sol"; + +contract ERC20VotesHarness is ERC20Votes { + constructor(string memory name, string memory symbol) ERC20Permit(name) ERC20(name, symbol) {} + + mapping(address => mapping(uint256 => uint256)) public _getPastVotes; + + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + _getPastVotes[from][block.number] += amount; + _getPastVotes[to][block.number] -= amount; + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual override{ + super._delegate(delegator, delegatee); + _getPastVotes[delegator][block.number] += balanceOf(delegator); + _getPastVotes[delegatee][block.number] -= balanceOf(delegator); + } +} diff --git a/contracts/mutants/ERC20VotesHarness/4/AVR/ERC20VotesHarness.sol b/contracts/mutants/ERC20VotesHarness/4/AVR/ERC20VotesHarness.sol new file mode 100644 index 00000000000..22aca924252 --- /dev/null +++ b/contracts/mutants/ERC20VotesHarness/4/AVR/ERC20VotesHarness.sol @@ -0,0 +1,28 @@ +import "../munged/token/ERC20/extensions/ERC20Votes.sol"; + +contract ERC20VotesHarness is ERC20Votes { + constructor(string memory name, string memory symbol) ERC20Permit(name) ERC20(name, symbol) {} + + mapping(address => mapping(uint256 => uint256)) public _getPastVotes; + + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + _getPastVotes[from][block.number] += amount; + _getPastVotes[to][block.number] -= amount; + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual override{ + super._delegate(delegator, delegatee); + _getPastVotes[delegator][block.number] += balanceOf(delegator); + _getPastVotes[delegatee][block.number] -= balanceOf(delegator); + } +} diff --git a/contracts/mutants/ERC20VotesHarness/4/GVR/ERC20VotesHarness.sol b/contracts/mutants/ERC20VotesHarness/4/GVR/ERC20VotesHarness.sol new file mode 100644 index 00000000000..472228092bb --- /dev/null +++ b/contracts/mutants/ERC20VotesHarness/4/GVR/ERC20VotesHarness.sol @@ -0,0 +1,28 @@ +import "../munged/token/ERC20/extensions/ERC20Votes.sol"; + +contract ERC20VotesHarness is ERC20Votes { + constructor(string memory name, string memory symbol) ERC20Permit(name) ERC20(name, symbol) {} + + mapping(address => mapping(uint256 => uint256)) public _getPastVotes; + + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + _getPastVotes[from][block.difficulty] -= amount; + _getPastVotes[to][block.difficulty] += amount; + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual override{ + super._delegate(delegator, delegatee); + _getPastVotes[delegator][block.difficulty] -= balanceOf(delegator); + _getPastVotes[delegatee][block.difficulty] += balanceOf(delegator); + } +} diff --git a/contracts/mutants/ERC20VotesHarness/original/ERC20VotesHarness.sol b/contracts/mutants/ERC20VotesHarness/original/ERC20VotesHarness.sol new file mode 100644 index 00000000000..5067ecfba8e --- /dev/null +++ b/contracts/mutants/ERC20VotesHarness/original/ERC20VotesHarness.sol @@ -0,0 +1,28 @@ +import "../munged/token/ERC20/extensions/ERC20Votes.sol"; + +contract ERC20VotesHarness is ERC20Votes { + constructor(string memory name, string memory symbol) ERC20Permit(name) ERC20(name, symbol) {} + + mapping(address => mapping(uint256 => uint256)) public _getPastVotes; + + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + _getPastVotes[from][block.number] -= amount; + _getPastVotes[to][block.number] += amount; + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual override{ + super._delegate(delegator, delegatee); + _getPastVotes[delegator][block.number] -= balanceOf(delegator); + _getPastVotes[delegatee][block.number] += balanceOf(delegator); + } +} diff --git a/contracts/mutants/ERC20VotesMock/1/CCD/ERC20VotesMock.sol b/contracts/mutants/ERC20VotesMock/1/CCD/ERC20VotesMock.sol new file mode 100644 index 00000000000..f65a51d7a94 --- /dev/null +++ b/contracts/mutants/ERC20VotesMock/1/CCD/ERC20VotesMock.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "../token/ERC20/extensions/ERC20Votes.sol"; + +contract ERC20VotesMock is ERC20Votes { + + + function mint(address account, uint256 amount) public { + _mint(account, amount); + } + + function burn(address account, uint256 amount) public { + _burn(account, amount); + } + + function getChainId() external view returns (uint256) { + return block.chainid; + } +} diff --git a/contracts/mutants/ERC20VotesMock/1/DLR/ERC20VotesMock.sol b/contracts/mutants/ERC20VotesMock/1/DLR/ERC20VotesMock.sol new file mode 100644 index 00000000000..c7947eee201 --- /dev/null +++ b/contracts/mutants/ERC20VotesMock/1/DLR/ERC20VotesMock.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "../token/ERC20/extensions/ERC20Votes.sol"; + +contract ERC20VotesMock is ERC20Votes { + constructor(string storage name, string memory symbol) ERC20(name, symbol) ERC20Permit(name) {} + + function mint(address account, uint256 amount) public { + _mint(account, amount); + } + + function burn(address account, uint256 amount) public { + _burn(account, amount); + } + + function getChainId() external view returns (uint256) { + return block.chainid; + } +} diff --git a/contracts/mutants/ERC20VotesMock/1/FVR/ERC20VotesMock.sol b/contracts/mutants/ERC20VotesMock/1/FVR/ERC20VotesMock.sol new file mode 100644 index 00000000000..bcbcf99c624 --- /dev/null +++ b/contracts/mutants/ERC20VotesMock/1/FVR/ERC20VotesMock.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "../token/ERC20/extensions/ERC20Votes.sol"; + +contract ERC20VotesMock is ERC20Votes { + constructor(string memory name, string memory symbol) ERC20(name, symbol) ERC20Permit(name) {} + + function mint(address account, uint256 amount) external { + _mint(account, amount); + } + + function burn(address account, uint256 amount) public { + _burn(account, amount); + } + + function getChainId() external view returns (uint256) { + return block.chainid; + } +} diff --git a/contracts/mutants/ERC20VotesMock/1/MOC/ERC20VotesMock.sol b/contracts/mutants/ERC20VotesMock/1/MOC/ERC20VotesMock.sol new file mode 100644 index 00000000000..cc4da507e1a --- /dev/null +++ b/contracts/mutants/ERC20VotesMock/1/MOC/ERC20VotesMock.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "../token/ERC20/extensions/ERC20Votes.sol"; + +contract ERC20VotesMock is ERC20Votes { + constructor(string memory name, string memory symbol) ERC20Permit(name) ERC20(name, symbol) {} + + function mint(address account, uint256 amount) public { + _mint(account, amount); + } + + function burn(address account, uint256 amount) public { + _burn(account, amount); + } + + function getChainId() external view returns (uint256) { + return block.chainid; + } +} diff --git a/contracts/mutants/ERC20VotesMock/1/MOD/ERC20VotesMock.sol b/contracts/mutants/ERC20VotesMock/1/MOD/ERC20VotesMock.sol new file mode 100644 index 00000000000..cc4da507e1a --- /dev/null +++ b/contracts/mutants/ERC20VotesMock/1/MOD/ERC20VotesMock.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "../token/ERC20/extensions/ERC20Votes.sol"; + +contract ERC20VotesMock is ERC20Votes { + constructor(string memory name, string memory symbol) ERC20Permit(name) ERC20(name, symbol) {} + + function mint(address account, uint256 amount) public { + _mint(account, amount); + } + + function burn(address account, uint256 amount) public { + _burn(account, amount); + } + + function getChainId() external view returns (uint256) { + return block.chainid; + } +} diff --git a/contracts/mutants/ERC20VotesMock/1/RSD/ERC20VotesMock.sol b/contracts/mutants/ERC20VotesMock/1/RSD/ERC20VotesMock.sol new file mode 100644 index 00000000000..fc83303793f --- /dev/null +++ b/contracts/mutants/ERC20VotesMock/1/RSD/ERC20VotesMock.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "../token/ERC20/extensions/ERC20Votes.sol"; + +contract ERC20VotesMock is ERC20Votes { + constructor(string memory name, string memory symbol) ERC20(name, symbol) ERC20Permit(name) {} + + function mint(address account, uint256 amount) public { + _mint(account, amount); + } + + function burn(address account, uint256 amount) public { + _burn(account, amount); + } + + function getChainId() external view returns (uint256) { + /* return block.chainid; */ + } +} diff --git a/contracts/mutants/ERC20VotesMock/2/DLR/ERC20VotesMock.sol b/contracts/mutants/ERC20VotesMock/2/DLR/ERC20VotesMock.sol new file mode 100644 index 00000000000..dc1fd579be0 --- /dev/null +++ b/contracts/mutants/ERC20VotesMock/2/DLR/ERC20VotesMock.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "../token/ERC20/extensions/ERC20Votes.sol"; + +contract ERC20VotesMock is ERC20Votes { + constructor(string storage name, string storage symbol) ERC20(name, symbol) ERC20Permit(name) {} + + function mint(address account, uint256 amount) public { + _mint(account, amount); + } + + function burn(address account, uint256 amount) public { + _burn(account, amount); + } + + function getChainId() external view returns (uint256) { + return block.chainid; + } +} diff --git a/contracts/mutants/ERC20VotesMock/2/FVR/ERC20VotesMock.sol b/contracts/mutants/ERC20VotesMock/2/FVR/ERC20VotesMock.sol new file mode 100644 index 00000000000..2d3ef8337db --- /dev/null +++ b/contracts/mutants/ERC20VotesMock/2/FVR/ERC20VotesMock.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "../token/ERC20/extensions/ERC20Votes.sol"; + +contract ERC20VotesMock is ERC20Votes { + constructor(string memory name, string memory symbol) ERC20(name, symbol) ERC20Permit(name) {} + + function mint(address account, uint256 amount) external { + _mint(account, amount); + } + + function burn(address account, uint256 amount) external { + _burn(account, amount); + } + + function getChainId() external view returns (uint256) { + return block.chainid; + } +} diff --git a/contracts/mutants/ERC20VotesMock/3/FVR/ERC20VotesMock.sol b/contracts/mutants/ERC20VotesMock/3/FVR/ERC20VotesMock.sol new file mode 100644 index 00000000000..e0986bc90ac --- /dev/null +++ b/contracts/mutants/ERC20VotesMock/3/FVR/ERC20VotesMock.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "../token/ERC20/extensions/ERC20Votes.sol"; + +contract ERC20VotesMock is ERC20Votes { + constructor(string memory name, string memory symbol) ERC20(name, symbol) ERC20Permit(name) {} + + function mint(address account, uint256 amount) external { + _mint(account, amount); + } + + function burn(address account, uint256 amount) external { + _burn(account, amount); + } + + function getChainId() public view returns (uint256) { + return block.chainid; + } +} diff --git a/contracts/mutants/ERC20VotesMock/original/ERC20VotesMock.sol b/contracts/mutants/ERC20VotesMock/original/ERC20VotesMock.sol new file mode 100644 index 00000000000..0975e8b9f7e --- /dev/null +++ b/contracts/mutants/ERC20VotesMock/original/ERC20VotesMock.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "../token/ERC20/extensions/ERC20Votes.sol"; + +contract ERC20VotesMock is ERC20Votes { + constructor(string memory name, string memory symbol) ERC20(name, symbol) ERC20Permit(name) {} + + function mint(address account, uint256 amount) public { + _mint(account, amount); + } + + function burn(address account, uint256 amount) public { + _burn(account, amount); + } + + function getChainId() external view returns (uint256) { + return block.chainid; + } +} diff --git a/contracts/mutants/ERC20VotesMockUpgradeable/1/DLR/ERC20VotesMockUpgradeable.sol b/contracts/mutants/ERC20VotesMockUpgradeable/1/DLR/ERC20VotesMockUpgradeable.sol new file mode 100644 index 00000000000..253a35271fd --- /dev/null +++ b/contracts/mutants/ERC20VotesMockUpgradeable/1/DLR/ERC20VotesMockUpgradeable.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "../token/ERC20/extensions/ERC20VotesUpgradeable.sol"; +import "../proxy/utils/Initializable.sol"; + +contract ERC20VotesMockUpgradeable is Initializable, ERC20VotesUpgradeable { + function __ERC20VotesMock_init(string storage name, string memory symbol) internal onlyInitializing { + __ERC20_init_unchained(name, symbol); + __EIP712_init_unchained(name, "1"); + __ERC20Permit_init_unchained(name); + } + + function __ERC20VotesMock_init_unchained(string memory, string memory) internal onlyInitializing {} + + function mint(address account, uint256 amount) public { + _mint(account, amount); + } + + function burn(address account, uint256 amount) public { + _burn(account, amount); + } + + function getChainId() external view returns (uint256) { + return block.chainid; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[50] private __gap; +} diff --git a/contracts/mutants/ERC20VotesMockUpgradeable/1/FVR/ERC20VotesMockUpgradeable.sol b/contracts/mutants/ERC20VotesMockUpgradeable/1/FVR/ERC20VotesMockUpgradeable.sol new file mode 100644 index 00000000000..c4c2e4e6ee5 --- /dev/null +++ b/contracts/mutants/ERC20VotesMockUpgradeable/1/FVR/ERC20VotesMockUpgradeable.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "../token/ERC20/extensions/ERC20VotesUpgradeable.sol"; +import "../proxy/utils/Initializable.sol"; + +contract ERC20VotesMockUpgradeable is Initializable, ERC20VotesUpgradeable { + function __ERC20VotesMock_init(string memory name, string memory symbol) public onlyInitializing { + __ERC20_init_unchained(name, symbol); + __EIP712_init_unchained(name, "1"); + __ERC20Permit_init_unchained(name); + } + + function __ERC20VotesMock_init_unchained(string memory, string memory) internal onlyInitializing {} + + function mint(address account, uint256 amount) public { + _mint(account, amount); + } + + function burn(address account, uint256 amount) public { + _burn(account, amount); + } + + function getChainId() external view returns (uint256) { + return block.chainid; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[50] private __gap; +} diff --git a/contracts/mutants/ERC20VotesMockUpgradeable/1/ILR/ERC20VotesMockUpgradeable.sol b/contracts/mutants/ERC20VotesMockUpgradeable/1/ILR/ERC20VotesMockUpgradeable.sol new file mode 100644 index 00000000000..e36dea56a7f --- /dev/null +++ b/contracts/mutants/ERC20VotesMockUpgradeable/1/ILR/ERC20VotesMockUpgradeable.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "../token/ERC20/extensions/ERC20VotesUpgradeable.sol"; +import "../proxy/utils/Initializable.sol"; + +contract ERC20VotesMockUpgradeable is Initializable, ERC20VotesUpgradeable { + function __ERC20VotesMock_init(string memory name, string memory symbol) internal onlyInitializing { + __ERC20_init_unchained(name, symbol); + __EIP712_init_unchained(name, "1"); + __ERC20Permit_init_unchained(name); + } + + function __ERC20VotesMock_init_unchained(string memory, string memory) internal onlyInitializing {} + + function mint(address account, uint256 amount) public { + _mint(account, amount); + } + + function burn(address account, uint256 amount) public { + _burn(account, amount); + } + + function getChainId() external view returns (uint256) { + return block.chainid; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[49] private __gap; +} diff --git a/contracts/mutants/ERC20VotesMockUpgradeable/1/MOI/ERC20VotesMockUpgradeable.sol b/contracts/mutants/ERC20VotesMockUpgradeable/1/MOI/ERC20VotesMockUpgradeable.sol new file mode 100644 index 00000000000..17e4405cf28 --- /dev/null +++ b/contracts/mutants/ERC20VotesMockUpgradeable/1/MOI/ERC20VotesMockUpgradeable.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "../token/ERC20/extensions/ERC20VotesUpgradeable.sol"; +import "../proxy/utils/Initializable.sol"; + +contract ERC20VotesMockUpgradeable is Initializable, ERC20VotesUpgradeable { + function __ERC20VotesMock_init(string memory name, string memory symbol) internal onlyInitializing { + __ERC20_init_unchained(name, symbol); + __EIP712_init_unchained(name, "1"); + __ERC20Permit_init_unchained(name); + } + + function __ERC20VotesMock_init_unchained(string memory, string memory) internal onlyInitializing {} + + function mint(address account, uint256 amount) public onlyInitializing { + _mint(account, amount); + } + + function burn(address account, uint256 amount) public { + _burn(account, amount); + } + + function getChainId() external view returns (uint256) { + return block.chainid; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[50] private __gap; +} diff --git a/contracts/mutants/ERC20VotesMockUpgradeable/1/RSD/ERC20VotesMockUpgradeable.sol b/contracts/mutants/ERC20VotesMockUpgradeable/1/RSD/ERC20VotesMockUpgradeable.sol new file mode 100644 index 00000000000..2654a94d02c --- /dev/null +++ b/contracts/mutants/ERC20VotesMockUpgradeable/1/RSD/ERC20VotesMockUpgradeable.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "../token/ERC20/extensions/ERC20VotesUpgradeable.sol"; +import "../proxy/utils/Initializable.sol"; + +contract ERC20VotesMockUpgradeable is Initializable, ERC20VotesUpgradeable { + function __ERC20VotesMock_init(string memory name, string memory symbol) internal onlyInitializing { + __ERC20_init_unchained(name, symbol); + __EIP712_init_unchained(name, "1"); + __ERC20Permit_init_unchained(name); + } + + function __ERC20VotesMock_init_unchained(string memory, string memory) internal onlyInitializing {} + + function mint(address account, uint256 amount) public { + _mint(account, amount); + } + + function burn(address account, uint256 amount) public { + _burn(account, amount); + } + + function getChainId() external view returns (uint256) { + /* return block.chainid; */ + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[50] private __gap; +} diff --git a/contracts/mutants/ERC20VotesMockUpgradeable/1/SLR/ERC20VotesMockUpgradeable.sol b/contracts/mutants/ERC20VotesMockUpgradeable/1/SLR/ERC20VotesMockUpgradeable.sol new file mode 100644 index 00000000000..beba1260b00 --- /dev/null +++ b/contracts/mutants/ERC20VotesMockUpgradeable/1/SLR/ERC20VotesMockUpgradeable.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "../token/ERC20/extensions/ERC20VotesUpgradeable.sol"; +import "../proxy/utils/Initializable.sol"; + +contract ERC20VotesMockUpgradeable is Initializable, ERC20VotesUpgradeable { + function __ERC20VotesMock_init(string memory name, string memory symbol) internal onlyInitializing { + __ERC20_init_unchained(name, symbol); + __EIP712_init_unchained(name, ""); + __ERC20Permit_init_unchained(name); + } + + function __ERC20VotesMock_init_unchained(string memory, string memory) internal onlyInitializing {} + + function mint(address account, uint256 amount) public { + _mint(account, amount); + } + + function burn(address account, uint256 amount) public { + _burn(account, amount); + } + + function getChainId() external view returns (uint256) { + return block.chainid; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[50] private __gap; +} diff --git a/contracts/mutants/ERC20VotesMockUpgradeable/1/VVR/ERC20VotesMockUpgradeable.sol b/contracts/mutants/ERC20VotesMockUpgradeable/1/VVR/ERC20VotesMockUpgradeable.sol new file mode 100644 index 00000000000..bbd12aa7336 --- /dev/null +++ b/contracts/mutants/ERC20VotesMockUpgradeable/1/VVR/ERC20VotesMockUpgradeable.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "../token/ERC20/extensions/ERC20VotesUpgradeable.sol"; +import "../proxy/utils/Initializable.sol"; + +contract ERC20VotesMockUpgradeable is Initializable, ERC20VotesUpgradeable { + function __ERC20VotesMock_init(string memory name, string memory symbol) internal onlyInitializing { + __ERC20_init_unchained(name, symbol); + __EIP712_init_unchained(name, "1"); + __ERC20Permit_init_unchained(name); + } + + function __ERC20VotesMock_init_unchained(string memory, string memory) internal onlyInitializing {} + + function mint(address account, uint256 amount) public { + _mint(account, amount); + } + + function burn(address account, uint256 amount) public { + _burn(account, amount); + } + + function getChainId() external view returns (uint256) { + return block.chainid; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[50] public __gap; +} diff --git a/contracts/mutants/ERC20VotesMockUpgradeable/2/DLR/ERC20VotesMockUpgradeable.sol b/contracts/mutants/ERC20VotesMockUpgradeable/2/DLR/ERC20VotesMockUpgradeable.sol new file mode 100644 index 00000000000..fd1c8b4fb35 --- /dev/null +++ b/contracts/mutants/ERC20VotesMockUpgradeable/2/DLR/ERC20VotesMockUpgradeable.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "../token/ERC20/extensions/ERC20VotesUpgradeable.sol"; +import "../proxy/utils/Initializable.sol"; + +contract ERC20VotesMockUpgradeable is Initializable, ERC20VotesUpgradeable { + function __ERC20VotesMock_init(string storage name, string storage symbol) internal onlyInitializing { + __ERC20_init_unchained(name, symbol); + __EIP712_init_unchained(name, "1"); + __ERC20Permit_init_unchained(name); + } + + function __ERC20VotesMock_init_unchained(string memory, string memory) internal onlyInitializing {} + + function mint(address account, uint256 amount) public { + _mint(account, amount); + } + + function burn(address account, uint256 amount) public { + _burn(account, amount); + } + + function getChainId() external view returns (uint256) { + return block.chainid; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[50] private __gap; +} diff --git a/contracts/mutants/ERC20VotesMockUpgradeable/2/FVR/ERC20VotesMockUpgradeable.sol b/contracts/mutants/ERC20VotesMockUpgradeable/2/FVR/ERC20VotesMockUpgradeable.sol new file mode 100644 index 00000000000..5fa80da24cf --- /dev/null +++ b/contracts/mutants/ERC20VotesMockUpgradeable/2/FVR/ERC20VotesMockUpgradeable.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "../token/ERC20/extensions/ERC20VotesUpgradeable.sol"; +import "../proxy/utils/Initializable.sol"; + +contract ERC20VotesMockUpgradeable is Initializable, ERC20VotesUpgradeable { + function __ERC20VotesMock_init(string memory name, string memory symbol) public onlyInitializing { + __ERC20_init_unchained(name, symbol); + __EIP712_init_unchained(name, "1"); + __ERC20Permit_init_unchained(name); + } + + function __ERC20VotesMock_init_unchained(string memory, string memory) public onlyInitializing {} + + function mint(address account, uint256 amount) public { + _mint(account, amount); + } + + function burn(address account, uint256 amount) public { + _burn(account, amount); + } + + function getChainId() external view returns (uint256) { + return block.chainid; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[50] private __gap; +} diff --git a/contracts/mutants/ERC20VotesMockUpgradeable/2/MOI/ERC20VotesMockUpgradeable.sol b/contracts/mutants/ERC20VotesMockUpgradeable/2/MOI/ERC20VotesMockUpgradeable.sol new file mode 100644 index 00000000000..5daf7a171ff --- /dev/null +++ b/contracts/mutants/ERC20VotesMockUpgradeable/2/MOI/ERC20VotesMockUpgradeable.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "../token/ERC20/extensions/ERC20VotesUpgradeable.sol"; +import "../proxy/utils/Initializable.sol"; + +contract ERC20VotesMockUpgradeable is Initializable, ERC20VotesUpgradeable { + function __ERC20VotesMock_init(string memory name, string memory symbol) internal onlyInitializing { + __ERC20_init_unchained(name, symbol); + __EIP712_init_unchained(name, "1"); + __ERC20Permit_init_unchained(name); + } + + function __ERC20VotesMock_init_unchained(string memory, string memory) internal onlyInitializing {} + + function mint(address account, uint256 amount) public onlyInitializing { + _mint(account, amount); + } + + function burn(address account, uint256 amount) public onlyInitializing { + _burn(account, amount); + } + + function getChainId() external view returns (uint256) { + return block.chainid; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[50] private __gap; +} diff --git a/contracts/mutants/ERC20VotesMockUpgradeable/3/DLR/ERC20VotesMockUpgradeable.sol b/contracts/mutants/ERC20VotesMockUpgradeable/3/DLR/ERC20VotesMockUpgradeable.sol new file mode 100644 index 00000000000..b07168c8f57 --- /dev/null +++ b/contracts/mutants/ERC20VotesMockUpgradeable/3/DLR/ERC20VotesMockUpgradeable.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "../token/ERC20/extensions/ERC20VotesUpgradeable.sol"; +import "../proxy/utils/Initializable.sol"; + +contract ERC20VotesMockUpgradeable is Initializable, ERC20VotesUpgradeable { + function __ERC20VotesMock_init(string storage name, string storage symbol) internal onlyInitializing { + __ERC20_init_unchained(name, symbol); + __EIP712_init_unchained(name, "1"); + __ERC20Permit_init_unchained(name); + } + + function __ERC20VotesMock_init_unchained(string storage, string memory) internal onlyInitializing {} + + function mint(address account, uint256 amount) public { + _mint(account, amount); + } + + function burn(address account, uint256 amount) public { + _burn(account, amount); + } + + function getChainId() external view returns (uint256) { + return block.chainid; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[50] private __gap; +} diff --git a/contracts/mutants/ERC20VotesMockUpgradeable/3/FVR/ERC20VotesMockUpgradeable.sol b/contracts/mutants/ERC20VotesMockUpgradeable/3/FVR/ERC20VotesMockUpgradeable.sol new file mode 100644 index 00000000000..0db9841fa02 --- /dev/null +++ b/contracts/mutants/ERC20VotesMockUpgradeable/3/FVR/ERC20VotesMockUpgradeable.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "../token/ERC20/extensions/ERC20VotesUpgradeable.sol"; +import "../proxy/utils/Initializable.sol"; + +contract ERC20VotesMockUpgradeable is Initializable, ERC20VotesUpgradeable { + function __ERC20VotesMock_init(string memory name, string memory symbol) public onlyInitializing { + __ERC20_init_unchained(name, symbol); + __EIP712_init_unchained(name, "1"); + __ERC20Permit_init_unchained(name); + } + + function __ERC20VotesMock_init_unchained(string memory, string memory) public onlyInitializing {} + + function mint(address account, uint256 amount) external { + _mint(account, amount); + } + + function burn(address account, uint256 amount) public { + _burn(account, amount); + } + + function getChainId() external view returns (uint256) { + return block.chainid; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[50] private __gap; +} diff --git a/contracts/mutants/ERC20VotesMockUpgradeable/4/DLR/ERC20VotesMockUpgradeable.sol b/contracts/mutants/ERC20VotesMockUpgradeable/4/DLR/ERC20VotesMockUpgradeable.sol new file mode 100644 index 00000000000..54fb134ae48 --- /dev/null +++ b/contracts/mutants/ERC20VotesMockUpgradeable/4/DLR/ERC20VotesMockUpgradeable.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "../token/ERC20/extensions/ERC20VotesUpgradeable.sol"; +import "../proxy/utils/Initializable.sol"; + +contract ERC20VotesMockUpgradeable is Initializable, ERC20VotesUpgradeable { + function __ERC20VotesMock_init(string storage name, string storage symbol) internal onlyInitializing { + __ERC20_init_unchained(name, symbol); + __EIP712_init_unchained(name, "1"); + __ERC20Permit_init_unchained(name); + } + + function __ERC20VotesMock_init_unchained(string storage, string storage) internal onlyInitializing {} + + function mint(address account, uint256 amount) public { + _mint(account, amount); + } + + function burn(address account, uint256 amount) public { + _burn(account, amount); + } + + function getChainId() external view returns (uint256) { + return block.chainid; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[50] private __gap; +} diff --git a/contracts/mutants/ERC20VotesMockUpgradeable/4/FVR/ERC20VotesMockUpgradeable.sol b/contracts/mutants/ERC20VotesMockUpgradeable/4/FVR/ERC20VotesMockUpgradeable.sol new file mode 100644 index 00000000000..486360fc3a3 --- /dev/null +++ b/contracts/mutants/ERC20VotesMockUpgradeable/4/FVR/ERC20VotesMockUpgradeable.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "../token/ERC20/extensions/ERC20VotesUpgradeable.sol"; +import "../proxy/utils/Initializable.sol"; + +contract ERC20VotesMockUpgradeable is Initializable, ERC20VotesUpgradeable { + function __ERC20VotesMock_init(string memory name, string memory symbol) public onlyInitializing { + __ERC20_init_unchained(name, symbol); + __EIP712_init_unchained(name, "1"); + __ERC20Permit_init_unchained(name); + } + + function __ERC20VotesMock_init_unchained(string memory, string memory) public onlyInitializing {} + + function mint(address account, uint256 amount) external { + _mint(account, amount); + } + + function burn(address account, uint256 amount) external { + _burn(account, amount); + } + + function getChainId() external view returns (uint256) { + return block.chainid; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[50] private __gap; +} diff --git a/contracts/mutants/ERC20VotesMockUpgradeable/5/FVR/ERC20VotesMockUpgradeable.sol b/contracts/mutants/ERC20VotesMockUpgradeable/5/FVR/ERC20VotesMockUpgradeable.sol new file mode 100644 index 00000000000..98b15f0fcb2 --- /dev/null +++ b/contracts/mutants/ERC20VotesMockUpgradeable/5/FVR/ERC20VotesMockUpgradeable.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "../token/ERC20/extensions/ERC20VotesUpgradeable.sol"; +import "../proxy/utils/Initializable.sol"; + +contract ERC20VotesMockUpgradeable is Initializable, ERC20VotesUpgradeable { + function __ERC20VotesMock_init(string memory name, string memory symbol) public onlyInitializing { + __ERC20_init_unchained(name, symbol); + __EIP712_init_unchained(name, "1"); + __ERC20Permit_init_unchained(name); + } + + function __ERC20VotesMock_init_unchained(string memory, string memory) public onlyInitializing {} + + function mint(address account, uint256 amount) external { + _mint(account, amount); + } + + function burn(address account, uint256 amount) external { + _burn(account, amount); + } + + function getChainId() public view returns (uint256) { + return block.chainid; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[50] private __gap; +} diff --git a/contracts/mutants/ERC20VotesMockUpgradeable/original/ERC20VotesMockUpgradeable.sol b/contracts/mutants/ERC20VotesMockUpgradeable/original/ERC20VotesMockUpgradeable.sol new file mode 100644 index 00000000000..2edea9d1183 --- /dev/null +++ b/contracts/mutants/ERC20VotesMockUpgradeable/original/ERC20VotesMockUpgradeable.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "../token/ERC20/extensions/ERC20VotesUpgradeable.sol"; +import "../proxy/utils/Initializable.sol"; + +contract ERC20VotesMockUpgradeable is Initializable, ERC20VotesUpgradeable { + function __ERC20VotesMock_init(string memory name, string memory symbol) internal onlyInitializing { + __ERC20_init_unchained(name, symbol); + __EIP712_init_unchained(name, "1"); + __ERC20Permit_init_unchained(name); + } + + function __ERC20VotesMock_init_unchained(string memory, string memory) internal onlyInitializing {} + + function mint(address account, uint256 amount) public { + _mint(account, amount); + } + + function burn(address account, uint256 amount) public { + _burn(account, amount); + } + + function getChainId() external view returns (uint256) { + return block.chainid; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[50] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/1/BOR/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/1/BOR/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..a7774c20028 --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/1/BOR/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos <= 0 ? 0 : _checkpoints[account][pos - 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/1/CSC/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/1/CSC/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..e3666665b6a --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/1/CSC/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (true) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/1/DLR/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/1/DLR/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..078c547e7fc --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/1/DLR/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint storage) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/1/EED/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/1/EED/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..5f7f0149d12 --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/1/EED/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + /* emit DelegateChanged(delegator, currentDelegate, delegatee); */ + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/1/EHC/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/1/EHC/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..69154921b69 --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/1/EHC/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + /* require(blockNumber < block.number, "ERC20Votes: block not yet mined"); */ + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/1/FVR/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/1/FVR/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..16a050816e3 --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/1/FVR/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() public onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/1/GVR/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/1/GVR/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..94bf081029d --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/1/GVR/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.difficulty, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/1/ILR/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/1/ILR/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..120314b1ce5 --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/1/ILR/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 1 ? 0 : _checkpoints[account][pos - 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/1/MCR/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/1/MCR/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..2427d9ea35e --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/1/MCR/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + sha256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/1/MOI/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/1/MOI/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..6e5c6491bf0 --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/1/MOI/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override onlyInitializing { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/1/ORFD/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/1/ORFD/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..3d4351dfe75 --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/1/ORFD/ERC20VotesUpgradeable.sol @@ -0,0 +1,260 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/1/RSD/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/1/RSD/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..0d8e4852f82 --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/1/RSD/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + /* return _checkpoints[account][pos]; */ + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/1/RVS/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/1/RVS/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..00df7032416 --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/1/RVS/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 newWeight, uint256 oldWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/1/SCEC/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/1/SCEC/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..00df7032416 --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/1/SCEC/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 newWeight, uint256 oldWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/1/SKD/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/1/SKD/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..154ebe798fc --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/1/SKD/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + _mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/1/SKI/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/1/SKI/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..8933ed57380 --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/1/SKI/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(super.delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/1/SLR/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/1/SLR/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..05389bfd826 --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/1/SLR/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256(""); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/1/VVR/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/1/VVR/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..d376c5ac0d4 --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/1/VVR/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 public constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/10/BOR/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/10/BOR/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..62eb6e8a938 --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/10/BOR/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos <= 0 ? 0 : _checkpoints[account][pos + 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber <= block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber <= block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low <= high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock >= blockNumber) { + high = mid; + } else { + low = mid - 1; + } + } + + return high <= 0 ? 0 : ckpts[high + 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp < expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/10/ILR/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/10/ILR/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..96747d52ddb --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/10/ILR/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 1 ? 1 : _checkpoints[account][pos - 0].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 1; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 0; + } + } + + return high == 1 ? 1 : ckpts[high - 0].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 1) { + if (src != address(1)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/10/RSD/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/10/RSD/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..4d8ef126811 --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/10/RSD/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + /* return _checkpoints[account][pos]; */ + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + /* return SafeCastUpgradeable.toUint32(_checkpoints[account].length); */ + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + /* return _delegates[account]; */ + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + /* return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; */ + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + /* return _checkpointsLookup(_checkpoints[account], blockNumber); */ + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + /* return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); */ + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + /* return high == 0 ? 0 : ckpts[high - 1].votes; */ + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + /* return type(uint224).max; */ + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + /* return a + b; */ + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + /* return a - b; */ + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/2/BOR/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/2/BOR/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..510e4ad4deb --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/2/BOR/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos <= 0 ? 0 : _checkpoints[account][pos + 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/2/CSC/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/2/CSC/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..311a56b6e00 --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/2/CSC/ERC20VotesUpgradeable.sol @@ -0,0 +1,260 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (true) { + high = mid; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/2/DLR/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/2/DLR/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..b29e4dd07fa --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/2/DLR/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint storage) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] memory ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/2/EED/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/2/EED/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..e7e1946ca2b --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/2/EED/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + /* emit DelegateChanged(delegator, currentDelegate, delegatee); */ + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + /* emit DelegateVotesChanged(src, oldWeight, newWeight); */ + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/2/EHC/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/2/EHC/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..d6bbbccab7c --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/2/EHC/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + /* require(blockNumber < block.number, "ERC20Votes: block not yet mined"); */ + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + /* require(blockNumber < block.number, "ERC20Votes: block not yet mined"); */ + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/2/FVR/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/2/FVR/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..44f9665dc55 --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/2/FVR/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() public onlyInitializing { + } + + function __ERC20Votes_init_unchained() public onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/2/GVR/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/2/GVR/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..a83d4b1411b --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/2/GVR/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.difficulty, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.difficulty, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/2/ILR/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/2/ILR/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..035b6dacd77 --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/2/ILR/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 1 ? 1 : _checkpoints[account][pos - 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/2/MCR/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/2/MCR/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..512514ec720 --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/2/MCR/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + sha256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(sha256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/2/MOI/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/2/MOI/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..38f584356ea --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/2/MOI/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override onlyInitializing { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override onlyInitializing { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/2/ORFD/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/2/ORFD/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..517821ab05b --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/2/ORFD/ERC20VotesUpgradeable.sol @@ -0,0 +1,257 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + + + /** + * @dev Gets the current votes balance for `account` + */ + + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/2/RSD/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/2/RSD/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..b8c61f5fb03 --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/2/RSD/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + /* return _checkpoints[account][pos]; */ + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + /* return SafeCastUpgradeable.toUint32(_checkpoints[account].length); */ + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/2/SKD/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/2/SKD/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..536960a210c --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/2/SKD/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + _mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + _burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/2/SKI/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/2/SKI/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..3ea9cd523dd --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/2/SKI/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(super.delegates(from), super.delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/2/VVR/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/2/VVR/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..7e76c58c725 --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/2/VVR/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 public constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] public _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/3/BOR/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/3/BOR/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..2661d47de99 --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/3/BOR/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos <= 0 ? 0 : _checkpoints[account][pos + 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber <= block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/3/CSC/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/3/CSC/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..ef69b47e64a --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/3/CSC/ERC20VotesUpgradeable.sol @@ -0,0 +1,260 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (true) { + high = mid; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (true) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/3/DLR/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/3/DLR/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..74396cf7b6b --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/3/DLR/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint storage) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] memory ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] memory ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/3/EED/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/3/EED/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..a9a5dd45cdc --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/3/EED/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + /* emit DelegateChanged(delegator, currentDelegate, delegatee); */ + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + /* emit DelegateVotesChanged(src, oldWeight, newWeight); */ + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + /* emit DelegateVotesChanged(dst, oldWeight, newWeight); */ + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/3/EHC/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/3/EHC/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..8eb45adb336 --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/3/EHC/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + /* require(blockNumber < block.number, "ERC20Votes: block not yet mined"); */ + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + /* require(blockNumber < block.number, "ERC20Votes: block not yet mined"); */ + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + /* require(block.timestamp <= expiry, "ERC20Votes: signature expired"); */ + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/3/FVR/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/3/FVR/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..7b6b8123eb5 --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/3/FVR/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() public onlyInitializing { + } + + function __ERC20Votes_init_unchained() public onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) public view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/3/GVR/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/3/GVR/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..b1b5b92fbb7 --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/3/GVR/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.difficulty, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.difficulty, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.number <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/3/ILR/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/3/ILR/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..02722bcb780 --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/3/ILR/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 1 ? 1 : _checkpoints[account][pos - 0].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/3/MOI/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/3/MOI/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..ba060e8fcb4 --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/3/MOI/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override onlyInitializing { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override onlyInitializing { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override onlyInitializing { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/3/ORFD/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/3/ORFD/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..7e4942c70f8 --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/3/ORFD/ERC20VotesUpgradeable.sol @@ -0,0 +1,254 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + + + /** + * @dev Gets the current votes balance for `account` + */ + + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/3/RSD/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/3/RSD/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..b5a722e0a92 --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/3/RSD/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + /* return _checkpoints[account][pos]; */ + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + /* return SafeCastUpgradeable.toUint32(_checkpoints[account].length); */ + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + /* return _delegates[account]; */ + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/3/SKD/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/3/SKD/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..debeb65d974 --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/3/SKD/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + _mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + _burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + _afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/3/SKI/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/3/SKI/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..4941858e710 --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/3/SKI/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(super.delegates(from), super.delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = super.delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/3/VVR/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/3/VVR/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..f963f691275 --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/3/VVR/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 public constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] public _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] public __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/4/BOR/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/4/BOR/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..e9880865ee0 --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/4/BOR/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos <= 0 ? 0 : _checkpoints[account][pos + 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber <= block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber <= block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/4/CSC/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/4/CSC/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..950b1b7fe5b --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/4/CSC/ERC20VotesUpgradeable.sol @@ -0,0 +1,260 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (true) { + high = mid; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (true) { + if (true) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/4/EHC/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/4/EHC/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..f6a11e309ba --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/4/EHC/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + /* require(blockNumber < block.number, "ERC20Votes: block not yet mined"); */ + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + /* require(blockNumber < block.number, "ERC20Votes: block not yet mined"); */ + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + /* require(block.timestamp <= expiry, "ERC20Votes: signature expired"); */ + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + /* require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); */ + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/4/FVR/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/4/FVR/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..8a0c479d61e --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/4/FVR/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() public onlyInitializing { + } + + function __ERC20Votes_init_unchained() public onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) public view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) public { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/4/GVR/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/4/GVR/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..654cf89e588 --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/4/GVR/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.difficulty, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.difficulty, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.number <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.difficulty) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/4/ILR/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/4/ILR/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..7f0b6723492 --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/4/ILR/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 1 ? 1 : _checkpoints[account][pos - 0].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 1; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/4/MOI/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/4/MOI/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..4308e5aa1c3 --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/4/MOI/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override onlyInitializing { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override onlyInitializing { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override onlyInitializing { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override onlyInitializing { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/4/ORFD/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/4/ORFD/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..eed8f2e3be2 --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/4/ORFD/ERC20VotesUpgradeable.sol @@ -0,0 +1,251 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + + + /** + * @dev Gets the current votes balance for `account` + */ + + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/4/RSD/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/4/RSD/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..71489897587 --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/4/RSD/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + /* return _checkpoints[account][pos]; */ + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + /* return SafeCastUpgradeable.toUint32(_checkpoints[account].length); */ + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + /* return _delegates[account]; */ + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + /* return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; */ + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/5/BOR/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/5/BOR/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..2587489efce --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/5/BOR/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos <= 0 ? 0 : _checkpoints[account][pos + 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber <= block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber <= block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low <= high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/5/CSC/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/5/CSC/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..ba4c58ebccc --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/5/CSC/ERC20VotesUpgradeable.sol @@ -0,0 +1,260 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (true) { + high = mid; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (true) { + if (true) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (true) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/5/EHC/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/5/EHC/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..9f9220834bf --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/5/EHC/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + /* require(blockNumber < block.number, "ERC20Votes: block not yet mined"); */ + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + /* require(blockNumber < block.number, "ERC20Votes: block not yet mined"); */ + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + /* require(block.timestamp <= expiry, "ERC20Votes: signature expired"); */ + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + /* require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); */ + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + /* require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); */ + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/5/FVR/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/5/FVR/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..a2b676ba91b --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/5/FVR/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() public onlyInitializing { + } + + function __ERC20Votes_init_unchained() public onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) public view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) public { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) public returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/5/GVR/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/5/GVR/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..6a4f4fcf1f6 --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/5/GVR/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.difficulty, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.difficulty, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.number <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.difficulty) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.difficulty), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/5/ILR/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/5/ILR/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..b11070b166f --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/5/ILR/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 1 ? 1 : _checkpoints[account][pos - 0].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 1; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 0; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/5/MOI/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/5/MOI/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..89b099dfb8e --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/5/MOI/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override onlyInitializing { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override onlyInitializing { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override onlyInitializing { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override onlyInitializing { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override onlyInitializing { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/5/ORFD/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/5/ORFD/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..2c1c9785424 --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/5/ORFD/ERC20VotesUpgradeable.sol @@ -0,0 +1,249 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + + + /** + * @dev Gets the current votes balance for `account` + */ + + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/5/RSD/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/5/RSD/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..34fc1a6c974 --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/5/RSD/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + /* return _checkpoints[account][pos]; */ + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + /* return SafeCastUpgradeable.toUint32(_checkpoints[account].length); */ + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + /* return _delegates[account]; */ + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + /* return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; */ + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + /* return _checkpointsLookup(_checkpoints[account], blockNumber); */ + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/6/BOR/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/6/BOR/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..2be0bb0cb0d --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/6/BOR/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos <= 0 ? 0 : _checkpoints[account][pos + 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber <= block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber <= block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low <= high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock >= blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/6/CSC/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/6/CSC/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..6a00ee7c9e6 --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/6/CSC/ERC20VotesUpgradeable.sol @@ -0,0 +1,260 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (true) { + high = mid; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (true) { + if (true) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (true) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (true) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/6/FVR/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/6/FVR/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..62358085eef --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/6/FVR/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() public onlyInitializing { + } + + function __ERC20Votes_init_unchained() public onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) public view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) public { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) public returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) public pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/6/ILR/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/6/ILR/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..ec0116b5e27 --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/6/ILR/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 1 ? 1 : _checkpoints[account][pos - 0].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 1; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 0; + } + } + + return high == 1 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/6/MOI/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/6/MOI/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..452393196d7 --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/6/MOI/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override onlyInitializing { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override onlyInitializing { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override onlyInitializing { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override onlyInitializing { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override onlyInitializing { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual onlyInitializing { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/6/ORFD/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/6/ORFD/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..a5e1c0b330b --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/6/ORFD/ERC20VotesUpgradeable.sol @@ -0,0 +1,232 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + + + /** + * @dev Gets the current votes balance for `account` + */ + + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + + + /** + * @dev Delegates votes from signer to `delegatee` + */ + + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/6/RSD/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/6/RSD/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..f4c4305c42b --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/6/RSD/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + /* return _checkpoints[account][pos]; */ + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + /* return SafeCastUpgradeable.toUint32(_checkpoints[account].length); */ + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + /* return _delegates[account]; */ + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + /* return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; */ + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + /* return _checkpointsLookup(_checkpoints[account], blockNumber); */ + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + /* return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); */ + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/7/BOR/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/7/BOR/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..c75c95cc9d4 --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/7/BOR/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos <= 0 ? 0 : _checkpoints[account][pos + 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber <= block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber <= block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low <= high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock >= blockNumber) { + high = mid; + } else { + low = mid - 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/7/CSC/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/7/CSC/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..0e04f553433 --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/7/CSC/ERC20VotesUpgradeable.sol @@ -0,0 +1,258 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (true) { + high = mid; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (true) { + if (true) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (true) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (true) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/7/FVR/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/7/FVR/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..b166dbcdb20 --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/7/FVR/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() public onlyInitializing { + } + + function __ERC20Votes_init_unchained() public onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) public view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) public { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) public returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) public pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) public pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/7/ILR/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/7/ILR/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..e462ba90c52 --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/7/ILR/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 1 ? 1 : _checkpoints[account][pos - 0].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 1; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 0; + } + } + + return high == 1 ? 1 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/7/MOI/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/7/MOI/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..0bb54b98c08 --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/7/MOI/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override onlyInitializing { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override onlyInitializing { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override onlyInitializing { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override onlyInitializing { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override onlyInitializing { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual onlyInitializing { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private onlyInitializing { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/7/ORFD/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/7/ORFD/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..fdbef7dd5ca --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/7/ORFD/ERC20VotesUpgradeable.sol @@ -0,0 +1,227 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + + + /** + * @dev Gets the current votes balance for `account` + */ + + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + + + /** + * @dev Delegates votes from signer to `delegatee` + */ + + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/7/RSD/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/7/RSD/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..65f2675bf8f --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/7/RSD/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + /* return _checkpoints[account][pos]; */ + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + /* return SafeCastUpgradeable.toUint32(_checkpoints[account].length); */ + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + /* return _delegates[account]; */ + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + /* return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; */ + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + /* return _checkpointsLookup(_checkpoints[account], blockNumber); */ + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + /* return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); */ + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + /* return high == 0 ? 0 : ckpts[high - 1].votes; */ + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/8/BOR/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/8/BOR/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..f7a08e5966b --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/8/BOR/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos <= 0 ? 0 : _checkpoints[account][pos + 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber <= block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber <= block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low <= high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock >= blockNumber) { + high = mid; + } else { + low = mid - 1; + } + } + + return high <= 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/8/ILR/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/8/ILR/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..452dd53c53e --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/8/ILR/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 1 ? 1 : _checkpoints[account][pos - 0].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 1; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 0; + } + } + + return high == 1 ? 1 : ckpts[high - 0].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/8/MOI/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/8/MOI/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..81483e70959 --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/8/MOI/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override onlyInitializing { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override onlyInitializing { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override onlyInitializing { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override onlyInitializing { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override onlyInitializing { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual onlyInitializing { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private onlyInitializing { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view onlyInitializing returns (uint256) op, + uint256 delta + ) private { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/8/ORFD/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/8/ORFD/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..3d300e4ef63 --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/8/ORFD/ERC20VotesUpgradeable.sol @@ -0,0 +1,223 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + + + /** + * @dev Gets the current votes balance for `account` + */ + + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + + + /** + * @dev Delegates votes from signer to `delegatee` + */ + + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/8/RSD/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/8/RSD/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..e0a09369d49 --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/8/RSD/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + /* return _checkpoints[account][pos]; */ + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + /* return SafeCastUpgradeable.toUint32(_checkpoints[account].length); */ + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + /* return _delegates[account]; */ + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + /* return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; */ + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + /* return _checkpointsLookup(_checkpoints[account], blockNumber); */ + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + /* return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); */ + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + /* return high == 0 ? 0 : ckpts[high - 1].votes; */ + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + /* return type(uint224).max; */ + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/9/BOR/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/9/BOR/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..a5bafc6abd7 --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/9/BOR/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos <= 0 ? 0 : _checkpoints[account][pos + 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber <= block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber <= block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low <= high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock >= blockNumber) { + high = mid; + } else { + low = mid - 1; + } + } + + return high <= 0 ? 0 : ckpts[high + 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/9/ILR/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/9/ILR/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..c2ee99445c0 --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/9/ILR/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 1 ? 1 : _checkpoints[account][pos - 0].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 1; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 0; + } + } + + return high == 1 ? 1 : ckpts[high - 0].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 1) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/9/ORFD/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/9/ORFD/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..286f9a592e2 --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/9/ORFD/ERC20VotesUpgradeable.sol @@ -0,0 +1,215 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + + + /** + * @dev Gets the current votes balance for `account` + */ + + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + + + /** + * @dev Delegates votes from signer to `delegatee` + */ + + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/9/RSD/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/9/RSD/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..a964edaa885 --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/9/RSD/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + /* return _checkpoints[account][pos]; */ + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + /* return SafeCastUpgradeable.toUint32(_checkpoints[account].length); */ + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + /* return _delegates[account]; */ + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + /* return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; */ + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + /* return _checkpointsLookup(_checkpoints[account], blockNumber); */ + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + /* return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); */ + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + /* return high == 0 ? 0 : ckpts[high - 1].votes; */ + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + /* return type(uint224).max; */ + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + /* return a + b; */ + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20VotesUpgradeable/original/ERC20VotesUpgradeable.sol b/contracts/mutants/ERC20VotesUpgradeable/original/ERC20VotesUpgradeable.sol new file mode 100644 index 00000000000..b3bd619d579 --- /dev/null +++ b/contracts/mutants/ERC20VotesUpgradeable/original/ERC20VotesUpgradeable.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) + +pragma solidity ^0.8.0; + +import "./draft-ERC20PermitUpgradeable.sol"; +import "../../../utils/math/MathUpgradeable.sol"; +import "../../../governance/utils/IVotesUpgradeable.sol"; +import "../../../utils/math/SafeCastUpgradeable.sol"; +import "../../../utils/cryptography/ECDSAUpgradeable.sol"; +import "../../../proxy/utils/Initializable.sol"; + +/** + * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, + * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. + * + * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. + * + * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either + * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting + * power can be queried through the public accessors {getVotes} and {getPastVotes}. + * + * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it + * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. + * + * _Available since v4.2._ + */ +abstract contract ERC20VotesUpgradeable is Initializable, IVotesUpgradeable, ERC20PermitUpgradeable { + function __ERC20Votes_init() internal onlyInitializing { + } + + function __ERC20Votes_init_unchained() internal onlyInitializing { + } + struct Checkpoint { + uint32 fromBlock; + uint224 votes; + } + + bytes32 private constant _DELEGATION_TYPEHASH = + keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); + + mapping(address => address) private _delegates; + mapping(address => Checkpoint[]) private _checkpoints; + Checkpoint[] private _totalSupplyCheckpoints; + + /** + * @dev Get the `pos`-th checkpoint for `account`. + */ + function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { + return _checkpoints[account][pos]; + } + + /** + * @dev Get number of checkpoints for `account`. + */ + function numCheckpoints(address account) public view virtual returns (uint32) { + return SafeCastUpgradeable.toUint32(_checkpoints[account].length); + } + + /** + * @dev Get the address `account` is currently delegating to. + */ + function delegates(address account) public view virtual override returns (address) { + return _delegates[account]; + } + + /** + * @dev Gets the current votes balance for `account` + */ + function getVotes(address account) public view virtual override returns (uint256) { + uint256 pos = _checkpoints[account].length; + return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; + } + + /** + * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_checkpoints[account], blockNumber); + } + + /** + * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. + * It is but NOT the sum of all the delegated votes! + * + * Requirements: + * + * - `blockNumber` must have been already mined + */ + function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { + require(blockNumber < block.number, "ERC20Votes: block not yet mined"); + return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); + } + + /** + * @dev Lookup a value in a list of (sorted) checkpoints. + */ + function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { + // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. + // + // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). + // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. + // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) + // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) + // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not + // out of bounds (in which case we're looking too far in the past and the result is 0). + // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is + // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out + // the same. + uint256 high = ckpts.length; + uint256 low = 0; + while (low < high) { + uint256 mid = MathUpgradeable.average(low, high); + if (ckpts[mid].fromBlock > blockNumber) { + high = mid; + } else { + low = mid + 1; + } + } + + return high == 0 ? 0 : ckpts[high - 1].votes; + } + + /** + * @dev Delegate votes from the sender to `delegatee`. + */ + function delegate(address delegatee) public virtual override { + _delegate(_msgSender(), delegatee); + } + + /** + * @dev Delegates votes from signer to `delegatee` + */ + function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s + ) public virtual override { + require(block.timestamp <= expiry, "ERC20Votes: signature expired"); + address signer = ECDSAUpgradeable.recover( + _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), + v, + r, + s + ); + require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); + _delegate(signer, delegatee); + } + + /** + * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). + */ + function _maxSupply() internal view virtual returns (uint224) { + return type(uint224).max; + } + + /** + * @dev Snapshots the totalSupply after it has been increased. + */ + function _mint(address account, uint256 amount) internal virtual override { + super._mint(account, amount); + require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); + + _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); + } + + /** + * @dev Snapshots the totalSupply after it has been decreased. + */ + function _burn(address account, uint256 amount) internal virtual override { + super._burn(account, amount); + + _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); + } + + /** + * @dev Move voting power when tokens are transferred. + * + * Emits a {DelegateVotesChanged} event. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual override { + super._afterTokenTransfer(from, to, amount); + + _moveVotingPower(delegates(from), delegates(to), amount); + } + + /** + * @dev Change delegation for `delegator` to `delegatee`. + * + * Emits events {DelegateChanged} and {DelegateVotesChanged}. + */ + function _delegate(address delegator, address delegatee) internal virtual { + address currentDelegate = delegates(delegator); + uint256 delegatorBalance = balanceOf(delegator); + _delegates[delegator] = delegatee; + + emit DelegateChanged(delegator, currentDelegate, delegatee); + + _moveVotingPower(currentDelegate, delegatee, delegatorBalance); + } + + function _moveVotingPower( + address src, + address dst, + uint256 amount + ) private { + if (src != dst && amount > 0) { + if (src != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); + emit DelegateVotesChanged(src, oldWeight, newWeight); + } + + if (dst != address(0)) { + (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); + emit DelegateVotesChanged(dst, oldWeight, newWeight); + } + } + } + + function _writeCheckpoint( + Checkpoint[] storage ckpts, + function(uint256, uint256) view returns (uint256) op, + uint256 delta + ) private returns (uint256 oldWeight, uint256 newWeight) { + uint256 pos = ckpts.length; + oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; + newWeight = op(oldWeight, delta); + + if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { + ckpts[pos - 1].votes = SafeCastUpgradeable.toUint224(newWeight); + } else { + ckpts.push(Checkpoint({fromBlock: SafeCastUpgradeable.toUint32(block.number), votes: SafeCastUpgradeable.toUint224(newWeight)})); + } + } + + function _add(uint256 a, uint256 b) private pure returns (uint256) { + return a + b; + } + + function _subtract(uint256 a, uint256 b) private pure returns (uint256) { + return a - b; + } + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps + */ + uint256[47] private __gap; +} diff --git a/contracts/mutants/ERC20WithFees/1/AOR/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/1/AOR/ERC20WithFees.sol new file mode 100644 index 00000000000..f42f9f8549b --- /dev/null +++ b/contracts/mutants/ERC20WithFees/1/AOR/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] -= amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/1/AVR/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/1/AVR/ERC20WithFees.sol new file mode 100644 index 00000000000..f42f9f8549b --- /dev/null +++ b/contracts/mutants/ERC20WithFees/1/AVR/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] -= amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/1/BLR/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/1/BLR/ERC20WithFees.sol new file mode 100644 index 00000000000..1246629767b --- /dev/null +++ b/contracts/mutants/ERC20WithFees/1/BLR/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return false; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/1/BOR/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/1/BOR/ERC20WithFees.sol new file mode 100644 index 00000000000..3f4414df765 --- /dev/null +++ b/contracts/mutants/ERC20WithFees/1/BOR/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance > amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/1/CCD/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/1/CCD/ERC20WithFees.sol new file mode 100644 index 00000000000..9011992d62b --- /dev/null +++ b/contracts/mutants/ERC20WithFees/1/CCD/ERC20WithFees.sol @@ -0,0 +1,421 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/1/CSC/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/1/CSC/ERC20WithFees.sol new file mode 100644 index 00000000000..5108908b396 --- /dev/null +++ b/contracts/mutants/ERC20WithFees/1/CSC/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (true) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/1/DLR/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/1/DLR/ERC20WithFees.sol new file mode 100644 index 00000000000..c5062b682b8 --- /dev/null +++ b/contracts/mutants/ERC20WithFees/1/DLR/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string storage name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/1/EED/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/1/EED/ERC20WithFees.sol new file mode 100644 index 00000000000..815ee55a5a7 --- /dev/null +++ b/contracts/mutants/ERC20WithFees/1/EED/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + /* emit Transfer(sender, recipient, amount); */ + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/1/EHC/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/1/EHC/ERC20WithFees.sol new file mode 100644 index 00000000000..d09f2668fab --- /dev/null +++ b/contracts/mutants/ERC20WithFees/1/EHC/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + /* require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); */ + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/1/FVR/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/1/FVR/ERC20WithFees.sol new file mode 100644 index 00000000000..c3249e2f1c8 --- /dev/null +++ b/contracts/mutants/ERC20WithFees/1/FVR/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) public onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/1/ICM/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/1/ICM/ERC20WithFees.sol new file mode 100644 index 00000000000..8c01e0a0241 --- /dev/null +++ b/contracts/mutants/ERC20WithFees/1/ICM/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply =- amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/1/ILR/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/1/ILR/ERC20WithFees.sol new file mode 100644 index 00000000000..9c2ef0395ba --- /dev/null +++ b/contracts/mutants/ERC20WithFees/1/ILR/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(1, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/1/LSC/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/1/LSC/ERC20WithFees.sol new file mode 100644 index 00000000000..8c01e0a0241 --- /dev/null +++ b/contracts/mutants/ERC20WithFees/1/LSC/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply =- amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/1/ORFD/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/1/ORFD/ERC20WithFees.sol new file mode 100644 index 00000000000..6996a4c52e9 --- /dev/null +++ b/contracts/mutants/ERC20WithFees/1/ORFD/ERC20WithFees.sol @@ -0,0 +1,422 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/1/RSD/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/1/RSD/ERC20WithFees.sol new file mode 100644 index 00000000000..8dc12274edb --- /dev/null +++ b/contracts/mutants/ERC20WithFees/1/RSD/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + /* return _name; */ + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/1/UORD/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/1/UORD/ERC20WithFees.sol new file mode 100644 index 00000000000..b69b3620b28 --- /dev/null +++ b/contracts/mutants/ERC20WithFees/1/UORD/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if ( isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/1/VVR/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/1/VVR/ERC20WithFees.sol new file mode 100644 index 00000000000..48af43e0101 --- /dev/null +++ b/contracts/mutants/ERC20WithFees/1/VVR/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 public _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/10/BOR/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/10/BOR/ERC20WithFees.sol new file mode 100644 index 00000000000..1db50b8440c --- /dev/null +++ b/contracts/mutants/ERC20WithFees/10/BOR/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance > amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance + amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] - addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance > subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance + subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender > address(0), "ERC20: transfer from the zero address"); + require(recipient > address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance > amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance + amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) || !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/10/EHC/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/10/EHC/ERC20WithFees.sol new file mode 100644 index 00000000000..55f77ac578a --- /dev/null +++ b/contracts/mutants/ERC20WithFees/10/EHC/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + /* require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); */ + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + /* require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); */ + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + /* require(sender != address(0), "ERC20: transfer from the zero address"); */ + /* require(recipient != address(0), "ERC20: transfer to the zero address"); */ + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + /* require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); */ + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + /* require(account != address(0), "ERC20: mint to the zero address"); */ + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + /* require(account != address(0), "ERC20: burn from the zero address"); */ + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + /* require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); */ + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + /* require(owner != address(0), "ERC20: approve from the zero address"); */ + /* require(spender != address(0), "ERC20: approve to the zero address"); */ + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/10/ILR/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/10/ILR/ERC20WithFees.sol new file mode 100644 index 00000000000..464eb8e77c5 --- /dev/null +++ b/contracts/mutants/ERC20WithFees/10/ILR/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(1, 999); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 17; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(1), "ERC20: transfer from the zero address"); + require(recipient != address(1), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 1; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(1), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(1), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(1), account, amount); + + _afterTokenTransfer(address(1), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/10/RSD/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/10/RSD/ERC20WithFees.sol new file mode 100644 index 00000000000..5848209ab97 --- /dev/null +++ b/contracts/mutants/ERC20WithFees/10/RSD/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + /* return _name; */ + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + /* return _symbol; */ + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + /* return 18; */ + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + /* return _totalSupply; */ + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + /* return _balances[account]; */ + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + /* return true; */ + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + /* return _allowances[owner][spender]; */ + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + /* return true; */ + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + /* return true; */ + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + /* return true; */ + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/2/AOR/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/2/AOR/ERC20WithFees.sol new file mode 100644 index 00000000000..94d3d77ee89 --- /dev/null +++ b/contracts/mutants/ERC20WithFees/2/AOR/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] -= amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] -= feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/2/AVR/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/2/AVR/ERC20WithFees.sol new file mode 100644 index 00000000000..94d3d77ee89 --- /dev/null +++ b/contracts/mutants/ERC20WithFees/2/AVR/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] -= amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] -= feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/2/BLR/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/2/BLR/ERC20WithFees.sol new file mode 100644 index 00000000000..37d8fd0c858 --- /dev/null +++ b/contracts/mutants/ERC20WithFees/2/BLR/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return false; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return false; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/2/BOR/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/2/BOR/ERC20WithFees.sol new file mode 100644 index 00000000000..9c15337b89b --- /dev/null +++ b/contracts/mutants/ERC20WithFees/2/BOR/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance > amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance + amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/2/CSC/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/2/CSC/ERC20WithFees.sol new file mode 100644 index 00000000000..e749e568eef --- /dev/null +++ b/contracts/mutants/ERC20WithFees/2/CSC/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (true) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (true) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/2/DLR/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/2/DLR/ERC20WithFees.sol new file mode 100644 index 00000000000..25a7e51863e --- /dev/null +++ b/contracts/mutants/ERC20WithFees/2/DLR/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string storage name_, string storage symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/2/EED/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/2/EED/ERC20WithFees.sol new file mode 100644 index 00000000000..f2df8f45f1f --- /dev/null +++ b/contracts/mutants/ERC20WithFees/2/EED/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + /* emit Transfer(sender, recipient, amount); */ + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + /* emit Transfer(address(0), account, amount); */ + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/2/EHC/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/2/EHC/ERC20WithFees.sol new file mode 100644 index 00000000000..11b480ba85d --- /dev/null +++ b/contracts/mutants/ERC20WithFees/2/EHC/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + /* require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); */ + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + /* require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); */ + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/2/FVR/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/2/FVR/ERC20WithFees.sol new file mode 100644 index 00000000000..e47c3caba72 --- /dev/null +++ b/contracts/mutants/ERC20WithFees/2/FVR/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) public onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) public onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/2/ILR/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/2/ILR/ERC20WithFees.sol new file mode 100644 index 00000000000..64838121eae --- /dev/null +++ b/contracts/mutants/ERC20WithFees/2/ILR/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(1, 999); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/2/ORFD/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/2/ORFD/ERC20WithFees.sol new file mode 100644 index 00000000000..fdb886cfeff --- /dev/null +++ b/contracts/mutants/ERC20WithFees/2/ORFD/ERC20WithFees.sol @@ -0,0 +1,420 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/2/RSD/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/2/RSD/ERC20WithFees.sol new file mode 100644 index 00000000000..ae19226b352 --- /dev/null +++ b/contracts/mutants/ERC20WithFees/2/RSD/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + /* return _name; */ + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + /* return _symbol; */ + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/2/UORD/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/2/UORD/ERC20WithFees.sol new file mode 100644 index 00000000000..227e4b44cc8 --- /dev/null +++ b/contracts/mutants/ERC20WithFees/2/UORD/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if ( isExcludedFromFees(sender) && isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/2/VVR/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/2/VVR/ERC20WithFees.sol new file mode 100644 index 00000000000..48249d8e525 --- /dev/null +++ b/contracts/mutants/ERC20WithFees/2/VVR/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 public _totalSupply; + + string public _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/3/AOR/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/3/AOR/ERC20WithFees.sol new file mode 100644 index 00000000000..69d4c9ae50b --- /dev/null +++ b/contracts/mutants/ERC20WithFees/3/AOR/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] -= amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] -= feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply -= amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/3/AVR/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/3/AVR/ERC20WithFees.sol new file mode 100644 index 00000000000..69d4c9ae50b --- /dev/null +++ b/contracts/mutants/ERC20WithFees/3/AVR/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] -= amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] -= feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply -= amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/3/BLR/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/3/BLR/ERC20WithFees.sol new file mode 100644 index 00000000000..f31b5c351ce --- /dev/null +++ b/contracts/mutants/ERC20WithFees/3/BLR/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return false; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return false; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return false; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/3/BOR/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/3/BOR/ERC20WithFees.sol new file mode 100644 index 00000000000..96cbedb8132 --- /dev/null +++ b/contracts/mutants/ERC20WithFees/3/BOR/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance > amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance + amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] - addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/3/CSC/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/3/CSC/ERC20WithFees.sol new file mode 100644 index 00000000000..0561934fe0a --- /dev/null +++ b/contracts/mutants/ERC20WithFees/3/CSC/ERC20WithFees.sol @@ -0,0 +1,422 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (true) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (true) { + emit PairAdded(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/3/DLR/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/3/DLR/ERC20WithFees.sol new file mode 100644 index 00000000000..c9354073f28 --- /dev/null +++ b/contracts/mutants/ERC20WithFees/3/DLR/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string storage name_, string storage symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string storage) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/3/EED/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/3/EED/ERC20WithFees.sol new file mode 100644 index 00000000000..9d1b9782077 --- /dev/null +++ b/contracts/mutants/ERC20WithFees/3/EED/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + /* emit Transfer(sender, recipient, amount); */ + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + /* emit Transfer(address(0), account, amount); */ + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + /* emit Transfer(account, address(0), amount); */ + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/3/EHC/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/3/EHC/ERC20WithFees.sol new file mode 100644 index 00000000000..9126de538f5 --- /dev/null +++ b/contracts/mutants/ERC20WithFees/3/EHC/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + /* require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); */ + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + /* require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); */ + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + /* require(sender != address(0), "ERC20: transfer from the zero address"); */ + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/3/FVR/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/3/FVR/ERC20WithFees.sol new file mode 100644 index 00000000000..467a7dd446e --- /dev/null +++ b/contracts/mutants/ERC20WithFees/3/FVR/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) public onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) public onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) public view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/3/ILR/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/3/ILR/ERC20WithFees.sol new file mode 100644 index 00000000000..9382901dea0 --- /dev/null +++ b/contracts/mutants/ERC20WithFees/3/ILR/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(1, 999); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 17; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/3/ORFD/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/3/ORFD/ERC20WithFees.sol new file mode 100644 index 00000000000..f8c7da218d4 --- /dev/null +++ b/contracts/mutants/ERC20WithFees/3/ORFD/ERC20WithFees.sol @@ -0,0 +1,418 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/3/RSD/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/3/RSD/ERC20WithFees.sol new file mode 100644 index 00000000000..8f746cd3258 --- /dev/null +++ b/contracts/mutants/ERC20WithFees/3/RSD/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + /* return _name; */ + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + /* return _symbol; */ + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + /* return 18; */ + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/3/VVR/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/3/VVR/ERC20WithFees.sol new file mode 100644 index 00000000000..d434b381611 --- /dev/null +++ b/contracts/mutants/ERC20WithFees/3/VVR/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 public _totalSupply; + + string public _name; + string public _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/4/AOR/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/4/AOR/ERC20WithFees.sol new file mode 100644 index 00000000000..7387bd113b3 --- /dev/null +++ b/contracts/mutants/ERC20WithFees/4/AOR/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] -= amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] -= feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply -= amount; + _balances[account] -= amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/4/AVR/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/4/AVR/ERC20WithFees.sol new file mode 100644 index 00000000000..7387bd113b3 --- /dev/null +++ b/contracts/mutants/ERC20WithFees/4/AVR/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] -= amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] -= feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply -= amount; + _balances[account] -= amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/4/BLR/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/4/BLR/ERC20WithFees.sol new file mode 100644 index 00000000000..6b9fab887a0 --- /dev/null +++ b/contracts/mutants/ERC20WithFees/4/BLR/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return false; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return false; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return false; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return false; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/4/BOR/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/4/BOR/ERC20WithFees.sol new file mode 100644 index 00000000000..e43c984b7f6 --- /dev/null +++ b/contracts/mutants/ERC20WithFees/4/BOR/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance > amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance + amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] - addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance > subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/4/DLR/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/4/DLR/ERC20WithFees.sol new file mode 100644 index 00000000000..9ba07b9b083 --- /dev/null +++ b/contracts/mutants/ERC20WithFees/4/DLR/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string storage name_, string storage symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string storage) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string storage) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/4/EED/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/4/EED/ERC20WithFees.sol new file mode 100644 index 00000000000..00d65d07d10 --- /dev/null +++ b/contracts/mutants/ERC20WithFees/4/EED/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + /* emit Transfer(sender, recipient, amount); */ + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + /* emit Transfer(address(0), account, amount); */ + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + /* emit Transfer(account, address(0), amount); */ + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + /* emit Approval(owner, spender, amount); */ + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/4/EHC/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/4/EHC/ERC20WithFees.sol new file mode 100644 index 00000000000..cf59d56e220 --- /dev/null +++ b/contracts/mutants/ERC20WithFees/4/EHC/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + /* require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); */ + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + /* require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); */ + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + /* require(sender != address(0), "ERC20: transfer from the zero address"); */ + /* require(recipient != address(0), "ERC20: transfer to the zero address"); */ + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/4/ILR/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/4/ILR/ERC20WithFees.sol new file mode 100644 index 00000000000..665dc75119d --- /dev/null +++ b/contracts/mutants/ERC20WithFees/4/ILR/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(1, 999); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 17; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(1), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/4/ORFD/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/4/ORFD/ERC20WithFees.sol new file mode 100644 index 00000000000..d973582deb2 --- /dev/null +++ b/contracts/mutants/ERC20WithFees/4/ORFD/ERC20WithFees.sol @@ -0,0 +1,416 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + + + /** + * @dev See {IERC20-totalSupply}. + */ + + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/4/RSD/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/4/RSD/ERC20WithFees.sol new file mode 100644 index 00000000000..4bddc2b3a31 --- /dev/null +++ b/contracts/mutants/ERC20WithFees/4/RSD/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + /* return _name; */ + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + /* return _symbol; */ + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + /* return 18; */ + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + /* return _totalSupply; */ + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/4/VVR/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/4/VVR/ERC20WithFees.sol new file mode 100644 index 00000000000..1a17c00e125 --- /dev/null +++ b/contracts/mutants/ERC20WithFees/4/VVR/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 public _totalSupply; + + string public _name; + string public _symbol; + + Fee internal fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/5/AOR/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/5/AOR/ERC20WithFees.sol new file mode 100644 index 00000000000..730b516121a --- /dev/null +++ b/contracts/mutants/ERC20WithFees/5/AOR/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] -= amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] -= feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply -= amount; + _balances[account] -= amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply += amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/5/AVR/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/5/AVR/ERC20WithFees.sol new file mode 100644 index 00000000000..730b516121a --- /dev/null +++ b/contracts/mutants/ERC20WithFees/5/AVR/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] -= amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] -= feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply -= amount; + _balances[account] -= amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply += amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/5/BLR/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/5/BLR/ERC20WithFees.sol new file mode 100644 index 00000000000..e2b0970d23c --- /dev/null +++ b/contracts/mutants/ERC20WithFees/5/BLR/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return false; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return false; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return false; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return false; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return false; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/5/BOR/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/5/BOR/ERC20WithFees.sol new file mode 100644 index 00000000000..4dc6bdb9c9b --- /dev/null +++ b/contracts/mutants/ERC20WithFees/5/BOR/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance > amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance + amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] - addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance > subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance + subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/5/EED/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/5/EED/ERC20WithFees.sol new file mode 100644 index 00000000000..361761bd43c --- /dev/null +++ b/contracts/mutants/ERC20WithFees/5/EED/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + /* emit Transfer(sender, recipient, amount); */ + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + /* emit Transfer(address(0), account, amount); */ + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + /* emit Transfer(account, address(0), amount); */ + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + /* emit Approval(owner, spender, amount); */ + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + /* emit FeeUpdated(numerator, denominator); */ + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/5/EHC/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/5/EHC/ERC20WithFees.sol new file mode 100644 index 00000000000..b5bfae5c75f --- /dev/null +++ b/contracts/mutants/ERC20WithFees/5/EHC/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + /* require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); */ + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + /* require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); */ + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + /* require(sender != address(0), "ERC20: transfer from the zero address"); */ + /* require(recipient != address(0), "ERC20: transfer to the zero address"); */ + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + /* require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); */ + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/5/ILR/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/5/ILR/ERC20WithFees.sol new file mode 100644 index 00000000000..0c11d570f51 --- /dev/null +++ b/contracts/mutants/ERC20WithFees/5/ILR/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(1, 999); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 17; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(1), "ERC20: transfer from the zero address"); + require(recipient != address(1), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/5/ORFD/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/5/ORFD/ERC20WithFees.sol new file mode 100644 index 00000000000..0edd07d649c --- /dev/null +++ b/contracts/mutants/ERC20WithFees/5/ORFD/ERC20WithFees.sol @@ -0,0 +1,414 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + + + /** + * @dev See {IERC20-totalSupply}. + */ + + + /** + * @dev See {IERC20-balanceOf}. + */ + + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/5/RSD/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/5/RSD/ERC20WithFees.sol new file mode 100644 index 00000000000..d38ab7a497b --- /dev/null +++ b/contracts/mutants/ERC20WithFees/5/RSD/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + /* return _name; */ + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + /* return _symbol; */ + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + /* return 18; */ + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + /* return _totalSupply; */ + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + /* return _balances[account]; */ + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/6/BOR/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/6/BOR/ERC20WithFees.sol new file mode 100644 index 00000000000..ac8ea3f9750 --- /dev/null +++ b/contracts/mutants/ERC20WithFees/6/BOR/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance > amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance + amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] - addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance > subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance + subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender > address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/6/EED/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/6/EED/ERC20WithFees.sol new file mode 100644 index 00000000000..2ff5bb5bb4c --- /dev/null +++ b/contracts/mutants/ERC20WithFees/6/EED/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + /* emit Transfer(sender, recipient, amount); */ + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + /* emit Transfer(address(0), account, amount); */ + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + /* emit Transfer(account, address(0), amount); */ + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + /* emit Approval(owner, spender, amount); */ + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + /* emit FeeUpdated(numerator, denominator); */ + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + /* emit PairAdded(pair); */ + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/6/EHC/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/6/EHC/ERC20WithFees.sol new file mode 100644 index 00000000000..cf19a340c07 --- /dev/null +++ b/contracts/mutants/ERC20WithFees/6/EHC/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + /* require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); */ + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + /* require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); */ + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + /* require(sender != address(0), "ERC20: transfer from the zero address"); */ + /* require(recipient != address(0), "ERC20: transfer to the zero address"); */ + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + /* require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); */ + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + /* require(account != address(0), "ERC20: mint to the zero address"); */ + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/6/ILR/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/6/ILR/ERC20WithFees.sol new file mode 100644 index 00000000000..9f52e878a66 --- /dev/null +++ b/contracts/mutants/ERC20WithFees/6/ILR/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(1, 999); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 17; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(1), "ERC20: transfer from the zero address"); + require(recipient != address(1), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 1; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/6/ORFD/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/6/ORFD/ERC20WithFees.sol new file mode 100644 index 00000000000..1e1b2606fb0 --- /dev/null +++ b/contracts/mutants/ERC20WithFees/6/ORFD/ERC20WithFees.sol @@ -0,0 +1,411 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + + + /** + * @dev See {IERC20-totalSupply}. + */ + + + /** + * @dev See {IERC20-balanceOf}. + */ + + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/6/RSD/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/6/RSD/ERC20WithFees.sol new file mode 100644 index 00000000000..4e1723451c8 --- /dev/null +++ b/contracts/mutants/ERC20WithFees/6/RSD/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + /* return _name; */ + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + /* return _symbol; */ + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + /* return 18; */ + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + /* return _totalSupply; */ + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + /* return _balances[account]; */ + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + /* return true; */ + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/7/BOR/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/7/BOR/ERC20WithFees.sol new file mode 100644 index 00000000000..2ed88e24b66 --- /dev/null +++ b/contracts/mutants/ERC20WithFees/7/BOR/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance > amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance + amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] - addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance > subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance + subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender > address(0), "ERC20: transfer from the zero address"); + require(recipient > address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/7/EED/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/7/EED/ERC20WithFees.sol new file mode 100644 index 00000000000..a86da6555d7 --- /dev/null +++ b/contracts/mutants/ERC20WithFees/7/EED/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + /* emit Transfer(sender, recipient, amount); */ + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + /* emit Transfer(address(0), account, amount); */ + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + /* emit Transfer(account, address(0), amount); */ + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + /* emit Approval(owner, spender, amount); */ + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + /* emit FeeUpdated(numerator, denominator); */ + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + /* emit PairAdded(pair); */ + } else { + /* emit PairRemoved(pair); */ + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/7/EHC/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/7/EHC/ERC20WithFees.sol new file mode 100644 index 00000000000..552567f3d22 --- /dev/null +++ b/contracts/mutants/ERC20WithFees/7/EHC/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + /* require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); */ + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + /* require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); */ + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + /* require(sender != address(0), "ERC20: transfer from the zero address"); */ + /* require(recipient != address(0), "ERC20: transfer to the zero address"); */ + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + /* require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); */ + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + /* require(account != address(0), "ERC20: mint to the zero address"); */ + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + /* require(account != address(0), "ERC20: burn from the zero address"); */ + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/7/ILR/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/7/ILR/ERC20WithFees.sol new file mode 100644 index 00000000000..a8836988f40 --- /dev/null +++ b/contracts/mutants/ERC20WithFees/7/ILR/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(1, 999); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 17; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(1), "ERC20: transfer from the zero address"); + require(recipient != address(1), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 1; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(1), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/7/ORFD/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/7/ORFD/ERC20WithFees.sol new file mode 100644 index 00000000000..f011a5ce2d3 --- /dev/null +++ b/contracts/mutants/ERC20WithFees/7/ORFD/ERC20WithFees.sol @@ -0,0 +1,409 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + + + /** + * @dev See {IERC20-totalSupply}. + */ + + + /** + * @dev See {IERC20-balanceOf}. + */ + + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + + + /** + * @dev See {IERC20-allowance}. + */ + + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/7/RSD/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/7/RSD/ERC20WithFees.sol new file mode 100644 index 00000000000..dc69b808dd4 --- /dev/null +++ b/contracts/mutants/ERC20WithFees/7/RSD/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + /* return _name; */ + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + /* return _symbol; */ + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + /* return 18; */ + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + /* return _totalSupply; */ + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + /* return _balances[account]; */ + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + /* return true; */ + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + /* return _allowances[owner][spender]; */ + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/8/BOR/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/8/BOR/ERC20WithFees.sol new file mode 100644 index 00000000000..5a60178549c --- /dev/null +++ b/contracts/mutants/ERC20WithFees/8/BOR/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance > amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance + amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] - addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance > subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance + subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender > address(0), "ERC20: transfer from the zero address"); + require(recipient > address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance > amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/8/EHC/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/8/EHC/ERC20WithFees.sol new file mode 100644 index 00000000000..a159a6603c6 --- /dev/null +++ b/contracts/mutants/ERC20WithFees/8/EHC/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + /* require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); */ + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + /* require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); */ + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + /* require(sender != address(0), "ERC20: transfer from the zero address"); */ + /* require(recipient != address(0), "ERC20: transfer to the zero address"); */ + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + /* require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); */ + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + /* require(account != address(0), "ERC20: mint to the zero address"); */ + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + /* require(account != address(0), "ERC20: burn from the zero address"); */ + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + /* require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); */ + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/8/ILR/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/8/ILR/ERC20WithFees.sol new file mode 100644 index 00000000000..d79b4f45764 --- /dev/null +++ b/contracts/mutants/ERC20WithFees/8/ILR/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(1, 999); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 17; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(1), "ERC20: transfer from the zero address"); + require(recipient != address(1), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 1; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(1), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(1), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/8/ORFD/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/8/ORFD/ERC20WithFees.sol new file mode 100644 index 00000000000..a1fcf57a7a8 --- /dev/null +++ b/contracts/mutants/ERC20WithFees/8/ORFD/ERC20WithFees.sol @@ -0,0 +1,406 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + + + /** + * @dev See {IERC20-totalSupply}. + */ + + + /** + * @dev See {IERC20-balanceOf}. + */ + + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + + + /** + * @dev See {IERC20-allowance}. + */ + + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/8/RSD/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/8/RSD/ERC20WithFees.sol new file mode 100644 index 00000000000..ac80fd40bf3 --- /dev/null +++ b/contracts/mutants/ERC20WithFees/8/RSD/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + /* return _name; */ + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + /* return _symbol; */ + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + /* return 18; */ + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + /* return _totalSupply; */ + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + /* return _balances[account]; */ + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + /* return true; */ + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + /* return _allowances[owner][spender]; */ + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + /* return true; */ + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/9/BOR/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/9/BOR/ERC20WithFees.sol new file mode 100644 index 00000000000..5a19800e2ca --- /dev/null +++ b/contracts/mutants/ERC20WithFees/9/BOR/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance > amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance + amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] - addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance > subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance + subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender > address(0), "ERC20: transfer from the zero address"); + require(recipient > address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance > amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance + amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/9/EHC/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/9/EHC/ERC20WithFees.sol new file mode 100644 index 00000000000..3c784060353 --- /dev/null +++ b/contracts/mutants/ERC20WithFees/9/EHC/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + /* require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); */ + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + /* require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); */ + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + /* require(sender != address(0), "ERC20: transfer from the zero address"); */ + /* require(recipient != address(0), "ERC20: transfer to the zero address"); */ + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + /* require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); */ + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + /* require(account != address(0), "ERC20: mint to the zero address"); */ + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + /* require(account != address(0), "ERC20: burn from the zero address"); */ + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + /* require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); */ + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + /* require(owner != address(0), "ERC20: approve from the zero address"); */ + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/9/ILR/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/9/ILR/ERC20WithFees.sol new file mode 100644 index 00000000000..d6ab46bdd14 --- /dev/null +++ b/contracts/mutants/ERC20WithFees/9/ILR/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(1, 999); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 17; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(1), "ERC20: transfer from the zero address"); + require(recipient != address(1), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 1; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(1), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(1), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(1), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/9/ORFD/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/9/ORFD/ERC20WithFees.sol new file mode 100644 index 00000000000..88de5108ee9 --- /dev/null +++ b/contracts/mutants/ERC20WithFees/9/ORFD/ERC20WithFees.sol @@ -0,0 +1,392 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + + + /** + * @dev See {IERC20-totalSupply}. + */ + + + /** + * @dev See {IERC20-balanceOf}. + */ + + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + + + /** + * @dev See {IERC20-allowance}. + */ + + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/9/RSD/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/9/RSD/ERC20WithFees.sol new file mode 100644 index 00000000000..3447f9e2374 --- /dev/null +++ b/contracts/mutants/ERC20WithFees/9/RSD/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + /* return _name; */ + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + /* return _symbol; */ + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + /* return 18; */ + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + /* return _totalSupply; */ + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + /* return _balances[account]; */ + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + /* return true; */ + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + /* return _allowances[owner][spender]; */ + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + /* return true; */ + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + /* return true; */ + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithFees/original/ERC20WithFees.sol b/contracts/mutants/ERC20WithFees/original/ERC20WithFees.sol new file mode 100644 index 00000000000..83f30a6e49f --- /dev/null +++ b/contracts/mutants/ERC20WithFees/original/ERC20WithFees.sol @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts v4.4.0 (token/ERC20/ERC20.sol) + +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import "@openzeppelin/contracts/utils/Context.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "./Recoverable.sol"; + +struct Fee { + uint128 numerator; + uint128 denominator; +} + +/** + * @dev Implementation of the {IERC20} interface. + * + * This implementation is agnostic to the way tokens are created. This means + * that a supply mechanism has to be added in a derived contract using {_mint}. + * For a generic mechanism see {ERC20PresetMinterPauser}. + * + * TIP: For a detailed writeup see our guide + * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How + * to implement supply mechanisms]. + * + * We have followed general OpenZeppelin Contracts guidelines: functions revert + * instead returning `false` on failure. This behavior is nonetheless + * conventional and does not conflict with the expectations of ERC20 + * applications. + * + * Additionally, an {Approval} event is emitted on calls to {transferFrom}. + * This allows applications to reconstruct the allowance for all accounts just + * by listening to said events. Other implementations of the EIP may not emit + * these events, as it isn't required by the specification. + * + * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} + * functions have been added to mitigate the well-known issues around setting + * allowances. See {IERC20-approve}. + */ +contract ERC20WithFees is Context, IERC20, IERC20Metadata, AccessControl, Recoverable { + mapping(address => uint256) private _balances; + + mapping(address => mapping(address => uint256)) private _allowances; + + uint256 private _totalSupply; + + string private _name; + string private _symbol; + + Fee public fee = Fee(0, 1000); + + mapping(address => bool) public isPair; + + /** + * @dev Sets the values for {name} and {symbol}. + * + * The default value of {decimals} is 18. To select a different value for + * {decimals} you should overload it. + * + * All two of these values are immutable: they can only be set once during + * construction. + */ + constructor(string memory name_, string memory symbol_) { + _name = name_; + _symbol = symbol_; + } + + /** + * @dev Returns the name of the token. + */ + function name() public view virtual override returns (string memory) { + return _name; + } + + /** + * @dev Returns the symbol of the token, usually a shorter version of the + * name. + */ + function symbol() public view virtual override returns (string memory) { + return _symbol; + } + + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. This is the value {ERC20} uses, unless this function is + * overridden; + * + * NOTE: This information is only used for _display_ purposes: it in + * no way affects any of the arithmetic of the contract, including + * {IERC20-balanceOf} and {IERC20-transfer}. + */ + function decimals() public view virtual override returns (uint8) { + return 18; + } + + /** + * @dev See {IERC20-totalSupply}. + */ + function totalSupply() public view virtual override returns (uint256) { + return _totalSupply; + } + + /** + * @dev See {IERC20-balanceOf}. + */ + function balanceOf(address account) public view virtual override returns (uint256) { + return _balances[account]; + } + + /** + * @dev See {IERC20-transfer}. + * + * Requirements: + * + * - `recipient` cannot be the zero address. + * - the caller must have a balance of at least `amount`. + */ + function transfer(address recipient, uint256 amount) public virtual override returns (bool) { + _transfer(_msgSender(), recipient, amount); + return true; + } + + /** + * @dev See {IERC20-allowance}. + */ + function allowance(address owner, address spender) public view virtual override returns (uint256) { + return _allowances[owner][spender]; + } + + /** + * @dev See {IERC20-approve}. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function approve(address spender, uint256 amount) public virtual override returns (bool) { + _approve(_msgSender(), spender, amount); + return true; + } + + /** + * @dev See {IERC20-transferFrom}. + * + * Emits an {Approval} event indicating the updated allowance. This is not + * required by the EIP. See the note at the beginning of {ERC20}. + * + * Requirements: + * + * - `sender` and `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + * - the caller must have allowance for ``sender``'s tokens of at least + * `amount`. + */ + function transferFrom( + address sender, + address recipient, + uint256 amount + ) public virtual override returns (bool) { + _transfer(sender, recipient, amount); + + uint256 currentAllowance = _allowances[sender][_msgSender()]; + require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance"); + unchecked { + _approve(sender, _msgSender(), currentAllowance - amount); + } + + return true; + } + + /** + * @dev Atomically increases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + */ + function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { + _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue); + return true; + } + + /** + * @dev Atomically decreases the allowance granted to `spender` by the caller. + * + * This is an alternative to {approve} that can be used as a mitigation for + * problems described in {IERC20-approve}. + * + * Emits an {Approval} event indicating the updated allowance. + * + * Requirements: + * + * - `spender` cannot be the zero address. + * - `spender` must have allowance for the caller of at least + * `subtractedValue`. + */ + function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { + uint256 currentAllowance = _allowances[_msgSender()][spender]; + require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); + unchecked { + _approve(_msgSender(), spender, currentAllowance - subtractedValue); + } + + return true; + } + + /** + * @dev Moves `amount` of tokens from `sender` to `recipient`. + * + * This internal function is equivalent to {transfer}, and can be used to + * e.g. implement automatic token fees, slashing mechanisms, etc. + * + * Emits a {Transfer} event. + * + * Requirements: + * + * - `sender` cannot be the zero address. + * - `recipient` cannot be the zero address. + * - `sender` must have a balance of at least `amount`. + */ + function _transfer( + address sender, + address recipient, + uint256 amount + ) internal virtual { + require(sender != address(0), "ERC20: transfer from the zero address"); + require(recipient != address(0), "ERC20: transfer to the zero address"); + + _beforeTokenTransfer(sender, recipient, amount); + + uint256 senderBalance = _balances[sender]; + require(senderBalance >= amount, "ERC20: transfer amount exceeds balance"); + unchecked { + _balances[sender] = senderBalance - amount; + } + + /** + @notice Adds fee support + */ + + uint feeAmount = 0; + /** + * @notice Checks if the fees should apply or not. + * if both sender and receiver aren't excluded from paying fees. + * if either sender or receiver are LP pairs. + */ + if (!isExcludedFromFees(sender) && !isExcludedFromFees(recipient) && (isPair[sender] || isPair[recipient])) { + feeAmount = amount * fee.numerator / fee.denominator; + } + _balances[recipient] += amount - feeAmount; + + /** + * @notice Increments Koku's address balance. + */ + _balances[address(this)] += feeAmount; + + emit Transfer(sender, recipient, amount); + + _afterTokenTransfer(sender, recipient, amount); + } + + /** @dev Creates `amount` tokens and assigns them to `account`, increasing + * the total supply. + * + * Emits a {Transfer} event with `from` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + */ + function _mint(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: mint to the zero address"); + + _beforeTokenTransfer(address(0), account, amount); + + _totalSupply += amount; + _balances[account] += amount; + emit Transfer(address(0), account, amount); + + _afterTokenTransfer(address(0), account, amount); + } + + /** + * @dev Destroys `amount` tokens from `account`, reducing the + * total supply. + * + * Emits a {Transfer} event with `to` set to the zero address. + * + * Requirements: + * + * - `account` cannot be the zero address. + * - `account` must have at least `amount` tokens. + */ + function _burn(address account, uint256 amount) internal virtual { + require(account != address(0), "ERC20: burn from the zero address"); + + _beforeTokenTransfer(account, address(0), amount); + + uint256 accountBalance = _balances[account]; + require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); + unchecked { + _balances[account] = accountBalance - amount; + } + _totalSupply -= amount; + + emit Transfer(account, address(0), amount); + + _afterTokenTransfer(account, address(0), amount); + } + + /** + * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. + * + * This internal function is equivalent to `approve`, and can be used to + * e.g. set automatic allowances for certain subsystems, etc. + * + * Emits an {Approval} event. + * + * Requirements: + * + * - `owner` cannot be the zero address. + * - `spender` cannot be the zero address. + */ + function _approve( + address owner, + address spender, + uint256 amount + ) internal virtual { + require(owner != address(0), "ERC20: approve from the zero address"); + require(spender != address(0), "ERC20: approve to the zero address"); + + _allowances[owner][spender] = amount; + emit Approval(owner, spender, amount); + } + + /** + * @dev Hook that is called before any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * will be transferred to `to`. + * - when `from` is zero, `amount` tokens will be minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens will be burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _beforeTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @dev Hook that is called after any transfer of tokens. This includes + * minting and burning. + * + * Calling conditions: + * + * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens + * has been transferred to `to`. + * - when `from` is zero, `amount` tokens have been minted for `to`. + * - when `to` is zero, `amount` of ``from``'s tokens have been burned. + * - `from` and `to` are never both zero. + * + * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. + */ + function _afterTokenTransfer( + address from, + address to, + uint256 amount + ) internal virtual {} + + /** + * @notice Adds fees taxing to liquidity pair. + * @param numerator The fee numerator. + * @param denominator The fee denominator. + */ + function setFee(uint128 numerator, uint128 denominator) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(denominator != 0, "Denominator must not equal 0."); + fee = Fee(numerator, denominator); + emit FeeUpdated(numerator, denominator); + } + + /** + * @notice Adds or removes a pair address from getting taxed. + * @param pair Pair address. + * @param value Boolean value to indicate whether we tax a pair or not. + */ + function setPair(address pair, bool value) external onlyRole(DEFAULT_ADMIN_ROLE) { + isPair[pair] = value; + if (value) { + emit PairAdded(pair); + } else { + emit PairRemoved(pair); + } + } + + /** + * @notice Checks if address is excluded from paying fees. + * The excluded addresses for now are the owner and the current KOKU's address. + * @param account Address to check. + */ + function isExcludedFromFees(address account) internal view returns (bool) { + return account == owner() || account == address(this); + } + + event FeeUpdated(uint numerator, uint denominator); + event PairAdded(address account); + event PairRemoved(address account); +} diff --git a/contracts/mutants/ERC20WithMetadataMock/1/CCD/ERC20WithMetadataMock.sol b/contracts/mutants/ERC20WithMetadataMock/1/CCD/ERC20WithMetadataMock.sol new file mode 100644 index 00000000000..cb1c941e769 --- /dev/null +++ b/contracts/mutants/ERC20WithMetadataMock/1/CCD/ERC20WithMetadataMock.sol @@ -0,0 +1,8 @@ +pragma solidity ^0.4.24; + +import "../token/ERC20/ERC20.sol"; +import "../drafts/ERC1046/TokenMetadata.sol"; + +contract ERC20WithMetadataMock is ERC20, ERC20WithMetadata { + +} diff --git a/contracts/mutants/ERC20WithMetadataMock/1/FVR/ERC20WithMetadataMock.sol b/contracts/mutants/ERC20WithMetadataMock/1/FVR/ERC20WithMetadataMock.sol new file mode 100644 index 00000000000..05211d8f1ed --- /dev/null +++ b/contracts/mutants/ERC20WithMetadataMock/1/FVR/ERC20WithMetadataMock.sol @@ -0,0 +1,11 @@ +pragma solidity ^0.4.24; + +import "../token/ERC20/ERC20.sol"; +import "../drafts/ERC1046/TokenMetadata.sol"; + +contract ERC20WithMetadataMock is ERC20, ERC20WithMetadata { + constructor(string tokenURI) internal + ERC20WithMetadata(tokenURI) + { + } +} diff --git a/contracts/mutants/ERC20WithMetadataMock/original/ERC20WithMetadataMock.sol b/contracts/mutants/ERC20WithMetadataMock/original/ERC20WithMetadataMock.sol new file mode 100644 index 00000000000..ec2d122a18b --- /dev/null +++ b/contracts/mutants/ERC20WithMetadataMock/original/ERC20WithMetadataMock.sol @@ -0,0 +1,11 @@ +pragma solidity ^0.4.24; + +import "../token/ERC20/ERC20.sol"; +import "../drafts/ERC1046/TokenMetadata.sol"; + +contract ERC20WithMetadataMock is ERC20, ERC20WithMetadata { + constructor(string tokenURI) public + ERC20WithMetadata(tokenURI) + { + } +} diff --git a/contracts/mutants/ERC20WithSupply/1/AOR/ERC20WithSupply.sol b/contracts/mutants/ERC20WithSupply/1/AOR/ERC20WithSupply.sol new file mode 100644 index 00000000000..0b84fdb36ab --- /dev/null +++ b/contracts/mutants/ERC20WithSupply/1/AOR/ERC20WithSupply.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "./ERC20.sol"; + +abstract contract ERC20WithSupply is ERC20 { + uint256 public totalSupply; + + function _mint(address account, uint256 amount) internal override { + balanceOf[account] = balanceOf[account] + amount; + totalSupply -= amount; + emit Transfer(address(0), account, amount); + } + + function _burn(address account, uint256 amount) internal override { + balanceOf[account] = balanceOf[account] - amount; + totalSupply -= amount; + emit Transfer(account, address(0), amount); + } +} diff --git a/contracts/mutants/ERC20WithSupply/1/AVR/ERC20WithSupply.sol b/contracts/mutants/ERC20WithSupply/1/AVR/ERC20WithSupply.sol new file mode 100644 index 00000000000..0b84fdb36ab --- /dev/null +++ b/contracts/mutants/ERC20WithSupply/1/AVR/ERC20WithSupply.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "./ERC20.sol"; + +abstract contract ERC20WithSupply is ERC20 { + uint256 public totalSupply; + + function _mint(address account, uint256 amount) internal override { + balanceOf[account] = balanceOf[account] + amount; + totalSupply -= amount; + emit Transfer(address(0), account, amount); + } + + function _burn(address account, uint256 amount) internal override { + balanceOf[account] = balanceOf[account] - amount; + totalSupply -= amount; + emit Transfer(account, address(0), amount); + } +} diff --git a/contracts/mutants/ERC20WithSupply/1/BOR/ERC20WithSupply.sol b/contracts/mutants/ERC20WithSupply/1/BOR/ERC20WithSupply.sol new file mode 100644 index 00000000000..fa5305159ad --- /dev/null +++ b/contracts/mutants/ERC20WithSupply/1/BOR/ERC20WithSupply.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "./ERC20.sol"; + +abstract contract ERC20WithSupply is ERC20 { + uint256 public totalSupply; + + function _mint(address account, uint256 amount) internal override { + balanceOf[account] = balanceOf[account] - amount; + totalSupply += amount; + emit Transfer(address(0), account, amount); + } + + function _burn(address account, uint256 amount) internal override { + balanceOf[account] = balanceOf[account] - amount; + totalSupply -= amount; + emit Transfer(account, address(0), amount); + } +} diff --git a/contracts/mutants/ERC20WithSupply/1/EED/ERC20WithSupply.sol b/contracts/mutants/ERC20WithSupply/1/EED/ERC20WithSupply.sol new file mode 100644 index 00000000000..7f32bb8318d --- /dev/null +++ b/contracts/mutants/ERC20WithSupply/1/EED/ERC20WithSupply.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "./ERC20.sol"; + +abstract contract ERC20WithSupply is ERC20 { + uint256 public totalSupply; + + function _mint(address account, uint256 amount) internal override { + balanceOf[account] = balanceOf[account] + amount; + totalSupply += amount; + /* emit Transfer(address(0), account, amount); */ + } + + function _burn(address account, uint256 amount) internal override { + balanceOf[account] = balanceOf[account] - amount; + totalSupply -= amount; + emit Transfer(account, address(0), amount); + } +} diff --git a/contracts/mutants/ERC20WithSupply/1/ICM/ERC20WithSupply.sol b/contracts/mutants/ERC20WithSupply/1/ICM/ERC20WithSupply.sol new file mode 100644 index 00000000000..ef404d11cd2 --- /dev/null +++ b/contracts/mutants/ERC20WithSupply/1/ICM/ERC20WithSupply.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "./ERC20.sol"; + +abstract contract ERC20WithSupply is ERC20 { + uint256 public totalSupply; + + function _mint(address account, uint256 amount) internal override { + balanceOf[account] = balanceOf[account] + amount; + totalSupply += amount; + emit Transfer(address(0), account, amount); + } + + function _burn(address account, uint256 amount) internal override { + balanceOf[account] = balanceOf[account] - amount; + totalSupply =- amount; + emit Transfer(account, address(0), amount); + } +} diff --git a/contracts/mutants/ERC20WithSupply/1/ILR/ERC20WithSupply.sol b/contracts/mutants/ERC20WithSupply/1/ILR/ERC20WithSupply.sol new file mode 100644 index 00000000000..ff2a388016c --- /dev/null +++ b/contracts/mutants/ERC20WithSupply/1/ILR/ERC20WithSupply.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "./ERC20.sol"; + +abstract contract ERC20WithSupply is ERC20 { + uint256 public totalSupply; + + function _mint(address account, uint256 amount) internal override { + balanceOf[account] = balanceOf[account] + amount; + totalSupply += amount; + emit Transfer(address(1), account, amount); + } + + function _burn(address account, uint256 amount) internal override { + balanceOf[account] = balanceOf[account] - amount; + totalSupply -= amount; + emit Transfer(account, address(0), amount); + } +} diff --git a/contracts/mutants/ERC20WithSupply/1/LSC/ERC20WithSupply.sol b/contracts/mutants/ERC20WithSupply/1/LSC/ERC20WithSupply.sol new file mode 100644 index 00000000000..ef404d11cd2 --- /dev/null +++ b/contracts/mutants/ERC20WithSupply/1/LSC/ERC20WithSupply.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "./ERC20.sol"; + +abstract contract ERC20WithSupply is ERC20 { + uint256 public totalSupply; + + function _mint(address account, uint256 amount) internal override { + balanceOf[account] = balanceOf[account] + amount; + totalSupply += amount; + emit Transfer(address(0), account, amount); + } + + function _burn(address account, uint256 amount) internal override { + balanceOf[account] = balanceOf[account] - amount; + totalSupply =- amount; + emit Transfer(account, address(0), amount); + } +} diff --git a/contracts/mutants/ERC20WithSupply/1/ORFD/ERC20WithSupply.sol b/contracts/mutants/ERC20WithSupply/1/ORFD/ERC20WithSupply.sol new file mode 100644 index 00000000000..ba06afd92a7 --- /dev/null +++ b/contracts/mutants/ERC20WithSupply/1/ORFD/ERC20WithSupply.sol @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "./ERC20.sol"; + +abstract contract ERC20WithSupply is ERC20 { + uint256 public totalSupply; + + + + function _burn(address account, uint256 amount) internal override { + balanceOf[account] = balanceOf[account] - amount; + totalSupply -= amount; + emit Transfer(account, address(0), amount); + } +} diff --git a/contracts/mutants/ERC20WithSupply/1/VVR/ERC20WithSupply.sol b/contracts/mutants/ERC20WithSupply/1/VVR/ERC20WithSupply.sol new file mode 100644 index 00000000000..a21cb1b3bf8 --- /dev/null +++ b/contracts/mutants/ERC20WithSupply/1/VVR/ERC20WithSupply.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "./ERC20.sol"; + +abstract contract ERC20WithSupply is ERC20 { + uint256 internal totalSupply; + + function _mint(address account, uint256 amount) internal override { + balanceOf[account] = balanceOf[account] + amount; + totalSupply += amount; + emit Transfer(address(0), account, amount); + } + + function _burn(address account, uint256 amount) internal override { + balanceOf[account] = balanceOf[account] - amount; + totalSupply -= amount; + emit Transfer(account, address(0), amount); + } +} diff --git a/contracts/mutants/ERC20WithSupply/2/AOR/ERC20WithSupply.sol b/contracts/mutants/ERC20WithSupply/2/AOR/ERC20WithSupply.sol new file mode 100644 index 00000000000..c5200e11601 --- /dev/null +++ b/contracts/mutants/ERC20WithSupply/2/AOR/ERC20WithSupply.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "./ERC20.sol"; + +abstract contract ERC20WithSupply is ERC20 { + uint256 public totalSupply; + + function _mint(address account, uint256 amount) internal override { + balanceOf[account] = balanceOf[account] + amount; + totalSupply -= amount; + emit Transfer(address(0), account, amount); + } + + function _burn(address account, uint256 amount) internal override { + balanceOf[account] = balanceOf[account] - amount; + totalSupply += amount; + emit Transfer(account, address(0), amount); + } +} diff --git a/contracts/mutants/ERC20WithSupply/2/AVR/ERC20WithSupply.sol b/contracts/mutants/ERC20WithSupply/2/AVR/ERC20WithSupply.sol new file mode 100644 index 00000000000..c5200e11601 --- /dev/null +++ b/contracts/mutants/ERC20WithSupply/2/AVR/ERC20WithSupply.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "./ERC20.sol"; + +abstract contract ERC20WithSupply is ERC20 { + uint256 public totalSupply; + + function _mint(address account, uint256 amount) internal override { + balanceOf[account] = balanceOf[account] + amount; + totalSupply -= amount; + emit Transfer(address(0), account, amount); + } + + function _burn(address account, uint256 amount) internal override { + balanceOf[account] = balanceOf[account] - amount; + totalSupply += amount; + emit Transfer(account, address(0), amount); + } +} diff --git a/contracts/mutants/ERC20WithSupply/2/BOR/ERC20WithSupply.sol b/contracts/mutants/ERC20WithSupply/2/BOR/ERC20WithSupply.sol new file mode 100644 index 00000000000..5f6015b5506 --- /dev/null +++ b/contracts/mutants/ERC20WithSupply/2/BOR/ERC20WithSupply.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "./ERC20.sol"; + +abstract contract ERC20WithSupply is ERC20 { + uint256 public totalSupply; + + function _mint(address account, uint256 amount) internal override { + balanceOf[account] = balanceOf[account] - amount; + totalSupply += amount; + emit Transfer(address(0), account, amount); + } + + function _burn(address account, uint256 amount) internal override { + balanceOf[account] = balanceOf[account] + amount; + totalSupply -= amount; + emit Transfer(account, address(0), amount); + } +} diff --git a/contracts/mutants/ERC20WithSupply/2/EED/ERC20WithSupply.sol b/contracts/mutants/ERC20WithSupply/2/EED/ERC20WithSupply.sol new file mode 100644 index 00000000000..408d3bd8293 --- /dev/null +++ b/contracts/mutants/ERC20WithSupply/2/EED/ERC20WithSupply.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "./ERC20.sol"; + +abstract contract ERC20WithSupply is ERC20 { + uint256 public totalSupply; + + function _mint(address account, uint256 amount) internal override { + balanceOf[account] = balanceOf[account] + amount; + totalSupply += amount; + /* emit Transfer(address(0), account, amount); */ + } + + function _burn(address account, uint256 amount) internal override { + balanceOf[account] = balanceOf[account] - amount; + totalSupply -= amount; + /* emit Transfer(account, address(0), amount); */ + } +} diff --git a/contracts/mutants/ERC20WithSupply/2/ILR/ERC20WithSupply.sol b/contracts/mutants/ERC20WithSupply/2/ILR/ERC20WithSupply.sol new file mode 100644 index 00000000000..b2e805c03c3 --- /dev/null +++ b/contracts/mutants/ERC20WithSupply/2/ILR/ERC20WithSupply.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "./ERC20.sol"; + +abstract contract ERC20WithSupply is ERC20 { + uint256 public totalSupply; + + function _mint(address account, uint256 amount) internal override { + balanceOf[account] = balanceOf[account] + amount; + totalSupply += amount; + emit Transfer(address(1), account, amount); + } + + function _burn(address account, uint256 amount) internal override { + balanceOf[account] = balanceOf[account] - amount; + totalSupply -= amount; + emit Transfer(account, address(1), amount); + } +} diff --git a/contracts/mutants/ERC20WithSupply/2/ORFD/ERC20WithSupply.sol b/contracts/mutants/ERC20WithSupply/2/ORFD/ERC20WithSupply.sol new file mode 100644 index 00000000000..712c01c0dac --- /dev/null +++ b/contracts/mutants/ERC20WithSupply/2/ORFD/ERC20WithSupply.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "./ERC20.sol"; + +abstract contract ERC20WithSupply is ERC20 { + uint256 public totalSupply; + + + + +} diff --git a/contracts/mutants/ERC20WithSupply/original/ERC20WithSupply.sol b/contracts/mutants/ERC20WithSupply/original/ERC20WithSupply.sol new file mode 100644 index 00000000000..5a43dd67099 --- /dev/null +++ b/contracts/mutants/ERC20WithSupply/original/ERC20WithSupply.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.0; + +import "./ERC20.sol"; + +abstract contract ERC20WithSupply is ERC20 { + uint256 public totalSupply; + + function _mint(address account, uint256 amount) internal override { + balanceOf[account] = balanceOf[account] + amount; + totalSupply += amount; + emit Transfer(address(0), account, amount); + } + + function _burn(address account, uint256 amount) internal override { + balanceOf[account] = balanceOf[account] - amount; + totalSupply -= amount; + emit Transfer(account, address(0), amount); + } +}