Having bool
values will make the compiler emit extra code to sanitize them. See https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/security/ReentrancyGuard.sol#L23
Having bool
values will make the compiler emit extra code to sanitize them. See https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/security/ReentrancyGuard.sol#L23
Line 96 can be done using unchecked math due to the if guard in line 95 (claimed > escrowedAmount
).
Having bool
values will make the compiler emit extra code to sanitize them. See https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/security/ReentrancyGuard.sol#L23
The IEscrow.Deposit
struct is initialized in line 108 by reading it from storage and copying it to memory. This is unnecessary since nothing is read from this struct during the function (and it doesn't make sense either, since this function enables the collateral meaning anything stored there should be empty/zeroed).
Line 164 can be done using unchecked math due to the if guard in line 163 (self.deposited[token].amount >= amount
holds true).
Line 202 can be done using unchecked math due to the if guard in line 200 (self.deposited[token].amount >= amount
holds true).
Line 195 overwrites the full Credit struct, but only the interestAccrued
member gets modified. Consider updating just this variable.
Line 206 overwrites the full Credit struct, but only the interestAccrued
member gets modified. Consider updating just this variable.
Line 144 can be done using unchecked math due to the if guard in line 143 (amount <= unusedTokens[credit.token]
holds true).
Line 101 can be done using unchecked math due to the if guard in line 100 (oldClaimTokens > newClaimTokens
holds true).
Line 109 can be done using unchecked math due to the if guard in line 105 (diff <= unused
holds true).
The Rate struct takes 2 storage slots. It can be shortened to a single slot if the lastAccrued
timestamp gets shortened to, for example, uint40 which should be enough until the year 36812. Rates will need to be shortened to uint108, but that should also be plenty of precision for credit rates.
Several contracts use delegatecalls to libraries in order to provide functionality which incurs in an extra gas cost
All of the libraries used in the codebase are defined as external functions, which will generate a delegatecall whenever they are used.
This is probably used to fight code size, which may be understandable in the line of credit contracts, since it groups the LineOfCredit, EscrowedLine and SpigotedLine under the SecuredLine contract.
But in the case of the Spigot and Escrow contracts, these almost map 1-1 with respect to their libraries (SpigotLib and EscrowLib), which makes no sense and incurs in extra gas costs.
Also the LineLib
library is a good candidate to be moved to internal functions, as the implementations are short and frequently used.