Open code423n4 opened 2 years ago
For update of Ownable inherited contract and use of the internal transfer ownership method: https://github.com/PaladinFinance/Paladin-Tokenomics/pull/1/commits/4d0840c9c9fe8a1a4b043d2a33696fea8bf9176c
QA & gas optimizations changes are done in the PR: https://github.com/PaladinFinance/Paladin-Tokenomics/pull/6 (some changes/tips were implemented, others are noted but won't be applied)
Really high quality Gas optimizations report
Using the latest code of openzeppelin
Ownable.sol
and use_transferOwnership
function at constructor ofPaladinRewardReserve.sol
Target codebase
Currently, it uses
transferOwnership
function at the constructor ofPaladinRewardReserve.sol
.https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/PaladinRewardReserve.sol#L25
Potential improvements
With following steps, it can reduce the deployment gas cost.
Step1: Use the latest Ownable.sol https://github.com/OpenZeppelin/openzeppelin-contracts/blob/2a4ca654046e65553af89355e24785e50735a92c/contracts/access/Ownable.sol
Step2:
_transferOwnership
internal function instead oftransferOwnership
function inPaladinRewardReserve.sol
Deployment Gas change
Using the latest code of openzeppelin
Ownable.sol
and use_transferOwnership
function at constructor ofHolyPaladinToken.sol
Target codebase
https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L187
Currently, it uses
transferOwnership
function at the constructor ofHolyPaladinToken.sol
.Potential improvements
With following steps, it can reduce the deployment gas cost.
Step1: Use the latest Ownable.sol https://github.com/OpenZeppelin/openzeppelin-contracts/blob/2a4ca654046e65553af89355e24785e50735a92c/contracts/access/Ownable.sol
Step2:
_transferOwnership
internal function instead oftransferOwnership
function inHolyPaladinToken.sol
Deployment Gas change
Usage of
Errors
can reduce gas cost and contract size at PaladinRewardReserve.solTarget codebase
https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/PaladinRewardReserve.sol#L29
https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/PaladinRewardReserve.sol#L37
https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/PaladinRewardReserve.sol#L45
It uses
require
but usingErrors
in solidity can reduce the deployment gas cost.Potential improvements
Deployment Gas change
No need to set false at
emergency
variable in HolyPaladinToken.solTarget codebase
https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L103
Potential improvements
The default value of bool is false. So there is no need to set false at
emergency
variable.Deployment Gas change
Usage of
Errors
can reduce gas cost and contract size at HolyPaladinToken.solTarget codebase
Where it uses
require
inHolyPaladinToken.sol
https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.solThere are 39 callers of
require
.Potential improvements
Use
Errors
instead ofrequire
. https://docs.soliditylang.org/en/v0.8.13/contracts.html?highlight=error#errors-and-the-revert-statementThe gas and size improvements after using
Errors
instead ofrequire
with "hPAL: No Lock" is shown below:There are 8 callers of
require(..., "hPAL: No Lock")
. https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L270 https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L286 https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L301 https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L348 https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L1237 https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L1246 https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L1272 https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L1281Only converting the above mentioned 8 callers has -6669 deployment gas cost reduction and -0.031 size reduction. There are 31 callers of
require
in HolyPaladinToken.sol, usingErrors
instead ofrequire
may potentially reduce many gas costs and sizes.Use
!= 0
instead of> 0
in HolyPaladinToken.solTarget codebase
https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L229 https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L385 https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L758 https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L800 https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L809 https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L819 https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L822 https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L1026 https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L1051 https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L1062 https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L1078 https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L1237 https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L1246 https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L1272 https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L1281 https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L1342
Potential improvements
Use
!= 0
instead of> 0
at the above mentioned codes. The variable is uint, so it will not be below 0 so it can just check!= 0
.Methods Gas change
Following methods in HolyPaladinToken.sol can reduce gas (from 5 to 20) by the above mentioned changes.
Deployment Gas change
Usage of unchecked can reduce the gas cost at claim function at HolyPaladinToken.sol
Target codebase
https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L392
claimAmount
will not be more thanclaimableRewards[msg.sender]
. Therefore,claimableRewards[msg.sender] -= claimAmount
can be wrapped by unchecked.Potential improvements
Wrap
claimableRewards[msg.sender] -= claimAmount
with unchecked.Method Gas change
Deployment Gas change
The usage of unchecked in average function in Math.sol can reduce deployment gas fee and contract size of HolyPaladinToken.sol
Target codebase
https://github.com/code-423n4/2022-03-paladin/blob/main/contracts/open-zeppelin/utils/Math.sol#L29
The above logic would not overflow, so can use unchecked.
Potential improvements
Deployment Gas change
Contract size change
The usage of unchecked in binary search can reduce deployment gas fee and contract size of HolyPaladinToken.sol
Target codebase
low = mid + 1
used in the binary search can be wrapped by uncheckedhttps://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L526 https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L698 https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L955 https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L987 https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L1019
Potential improvements
Wrap
low = mid + 1
by unchecked.Deployment Gas change
Contract size change
Some
currentUserLockIndex
varaible does not need to be defined in HolyPalatinToken.solTarget codebase
https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L272-L273 https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L288-L289 https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L1173-L1174 https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L1241-L1242 https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L1276-L1277 https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L1347-L1348
Some
currentUserLockIndex
varaibles is defined even though they are used once. Not defining variables can reduce gas cost and contract size.Potential improvements
Avoid defining
currentUserLockIndex
variable as follows:Deployment Gas change
Methods Gas change
Contract size change
It can reduce about 0.6% of the size of HolyPaladinToken.sol.
The logic to call
EmergencyBlock()
in emergency can be put in private functionTarget codebase
https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L221 https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L244 https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L254 https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L269 https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L285 https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L300 https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L312 https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L328 https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L347 https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L372 https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L381 https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L403 https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L412
Following check is called by 13 callsites. This can be put into the private function to reduce the contract size and deployment gas cost.
Potential improvements
Define a private function to include the above mentioned logic, and use isEmergent function at each callsite.
Gas change
Please note that the method gas fee increases while deployment gas fee reduces. So it depends on what this project prioritizes.
Method gas fee Some methods have 10 ~ 30 increase of method gas cost.
Deployment gas fee
Contract size change
It can reduce about 1.3% of the size of HolyPaladinToken.sol.
Not defining lastUserLockIndex variable decreases contract size and gas cost
Target codebase
https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L456-L457 https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L709-L710
Potential improvements
Gas change
Contract size change
It can reduce about 0.2% of the size of HolyPaladinToken.sol.
Definitions senderCooldown and receiverBalance variables are not necessary at getNewReceiverCooldown function in HolyPaladinToken.sol
Target codebase
https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L426-L427
Definitions senderCooldown and receiverBalance variables are not necessary at getNewReceiverCooldown function in HolyPaladinToken.sol
Potential improvements
Avoid defining the above mentioned variables.
Deployment gas change
Contract size change
Not defining previousToBalance and previousFromBalance variables can reduce gas cost and contract size
Target codebase
https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L897-L898
https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L902-L903
Potential improvements
Avoid defining previousToBalance and previousFromBalance.
Method gas change
Following methods in HolyPaladinToken.sol can reduce around 10~20 gas cost
Deployment gas change
Contract size change
Avoiding calling balanceOf(user) multiple times can reduce deployment gas cost
Target codebase
https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L558-L560
https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L570-L572
Potential improvements
Deployment gas change
Contract size change
Avoid defining at _getNewIndex function in HolyPaladinToken.sol can reduce contract size and gas cost
Target codebase
https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L748-L755
ellapsedTime variable does not need to be defined.
Potential improvements
Avoid defining ellapsedTime variable.
Method gas change
This change reduces the method gas cost of more than 10 functions. The reductions are around 10~20.
Deployment gas change
Contract size change
Avoiding defining _currentDropPerSecond and newIndex at _updateRewardState function in HolyPaladinToken.sol can reduce gas cost and contract size
Target codebase
https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L768-L772
Potential improvements
Method gas change
This change reduces the method gas cost of more than 10 functions. The reductions are around 10~20.
Deployment gas change
Contract size change
Not using UserLockRewardVars struct in _getUserAccruedRewards function can greatly reduces gas cost and contract size
Target codebase
https://github.com/code-423n4/2022-03-paladin/blob/9c26ec8556298fb1dc3cf71f471aadad3a5c74a0/contracts/HolyPaladinToken.sol#L805-L848
UserLockRewardVars
struct does not need to be used.Potential improvements
Here is an example codebase which avoids using
UserLockRewardVars memory vars
.In this example, it also does not define
userStakedBalance
variable.Method gas change
This change reduces the method gas cost of more than 10 functions. The reductions are around 100~200.
Deployment gas change
Contract size change