You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
It is possible that the DebtToken is not necessary, its functionality is to keep track of the amount of debt that an address has, but this debt is not linked to the projects, so either a DebtToken contract is created per project, or this amount is a sum of all the debts of the account. It is possible that the project can be redesigned to only have a debt mapping and thus eliminate this contract, with the consequent gas savings and also improving debt traceability.
2. Use Custom Errors instead of Revert Strings to save Gas
Custom errors from Solidity 0.8.4 are cheaper than revert strings (cheaper deployment cost and runtime cost when the revert condition is met)
Source Custom Errors in Solidity:
Starting from Solidity v0.8.4, there is a convenient and gas-efficient way to explain to users why an operation failed through the use of custom errors. Until now, you could already use strings to give more information about failures (e.g., revert("Insufficient funds.");), but they are rather expensive, especially when it comes to deploy cost, and it is difficult to use dynamic information in them.
Custom errors are defined using the error statement, which can be used inside and outside of contracts (including interfaces and libraries).
Reduce the size of error messages (Long revert Strings)
Shortening revert strings to fit in 32 bytes will decrease deployment time gas and will decrease runtime gas when the revert condition is met.
Revert strings that are longer than 32 bytes require at least one additional mstore, along with additional overhead for computing memory offset, etc.
In this case, the statements are short, so it is recommended to use custom errors.
According to the documentation The status None is not defined:
Task Entity defined by a cost, a subcontractor, and a status. a task can be **Inactive, Active or Complete**. Tasks can be flagged as Allocated when budget for this task has bee provisioned. When subcontractor confirms the assignment on a task it is being flagged as SCConfirmed
if we use Inactive in the first position, or we remove None like this:
++i costs less gas compared to i++ or i += 1 for unsigned integer, as pre-increment is cheaper (about 5 gas per iteration). This statement is true even with the optimizer enabled.
i++ increments i and returns the initial value of i. Which means:
uint i =1;
i++; // == 1 but i == 2
But ++i returns the actual incremented value:
uint i =1;
++i; // == 2 and i == 2 too, so no need for a temporary variable
In the first case, the compiler has to create a temporary variable (when used) for returning 1 instead of 2
I suggest using ++i instead of i++ to increment the value of an uint variable. Same thing for --i and i--
5. There's no need to set default values for variables
If a variable is not set/initialized, the default value is assumed (0, false, 0x0 ... depending on the data type). You are simply wasting gas if you directly initialize it with its default value.
Changing the order of the signatures it's possible to reduce the logic and the contract size.
+ checkSignatureValidity(contractor, _hash, _signature, 0);- if (contractorDelegated) {+ if (!contractorDelegated) {+ checkSignatureValidity(builder, _hash, _signature, 1);- // Check contractor's signature- checkSignatureValidity(contractor, _hash, _signature, 0);
}
- // When builder has not delegated rights to contractor- else {- // Check for both B and GC signatures- checkSignatureValidity(builder, _hash, _signature, 0);- checkSignatureValidity(contractor, _hash, _signature, 1);- }
Gas
1. Is
DebtToken
needed?It is possible that the
DebtToken
is not necessary, its functionality is to keep track of the amount of debt that an address has, but this debt is not linked to the projects, so either aDebtToken
contract is created per project, or this amount is a sum of all the debts of the account. It is possible that the project can be redesigned to only have a debt mapping and thus eliminate this contract, with the consequent gas savings and also improving debt traceability.Affected source code:
2. Use Custom Errors instead of Revert Strings to save Gas
Custom errors from Solidity 0.8.4 are cheaper than revert strings (cheaper deployment cost and runtime cost when the revert condition is met)
Source Custom Errors in Solidity:
Starting from Solidity v0.8.4, there is a convenient and gas-efficient way to explain to users why an operation failed through the use of custom errors. Until now, you could already use strings to give more information about failures (e.g., revert("Insufficient funds.");), but they are rather expensive, especially when it comes to deploy cost, and it is difficult to use dynamic information in them.
Custom errors are defined using the error statement, which can be used inside and outside of contracts (including interfaces and libraries).
Reduce the size of error messages (Long revert Strings)
Shortening revert strings to fit in 32 bytes will decrease deployment time gas and will decrease runtime gas when the revert condition is met.
Revert strings that are longer than 32 bytes require at least one additional mstore, along with additional overhead for computing memory offset, etc.
In this case, the statements are short, so it is recommended to use custom errors.
Affected source code:
3. Remove None
According to the documentation The status
None
is not defined:if we use Inactive in the first position, or we remove
None
like this:We can avoid to set the
Inactive
state in everyinitialize
calls.Affected source code:
4.
++i
costs less gas compared toi++
ori += 1
++i
costs less gas compared toi++
ori += 1
for unsigned integer, as pre-increment is cheaper (about 5 gas per iteration). This statement is true even with the optimizer enabled.i++
incrementsi
and returns the initial value ofi
. Which means:But
++i
returns the actual incremented value:In the first case, the compiler has to create a temporary variable (when used) for returning
1
instead of2
I suggest using
++i
instead ofi++
to increment the value of an uint variable. Same thing for--i
andi--
Affected source code:
5. There's no need to set default values for variables
If a variable is not set/initialized, the default value is assumed (0,
false
, 0x0 ... depending on the data type). You are simply wasting gas if you directly initialize it with its default value.Affected source code:
6. Don't use storage variables for loops condition
It's cheaper to cache the storage variable inside a local variable and iterate over it.
Affected source code:
7. Improve deserialization
It's possible to save a lot of logic (and gas) if decode the
_actionType
as an enum.Affected source code:
8. Reorder conditionals to be cheaper
It's better to check first the internal checks, and after it, do the external calls.
Affected source code:
9. Save storage access
The method
mintNFT
returns theprojectCount
storage value as memory variable, so it's better to reuse this value instead of call the storage again.Affected source code:
10. Reduce code size
Changing the order of the signatures it's possible to reduce the logic and the contract size.
Affected source code:
Affected source code:
11. Improve logic
It doesn't need to delete or check the signature always. It's better to do the logic according that what happened.
Affected source code:
Affected source code:
It's not needed to emit the '0x' value, and it's cheaper to emit an empty one.
Affected source code:
12. Use
memory
insteadstorage
Since all the values of the
ProjectDetails
struct are returned, it is cheaper to avoid continuous storage accesses and usememory
.Affected source code:
The text was updated successfully, but these errors were encountered: