Platform: Code4rena
Start Date: 30/06/2023
Pot Size: $100,000 USDC
Total HM: 8
Participants: 22
Period: 14 days
Judge: Trust
Total Solo HM: 6
Id: 253
League: ETH
Rank: 14/22
Findings: 2
Award: $93.68
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: gpersoon
Also found by: DavidGiladi, MiloTruck, Rolezn, banpaleo5, catellatech, matrix_0wl, naman1778, vnavascues
60.1995 USDC - $60.20
Issue | |
---|---|
NC-1 | ADD A TIMELOCK TO CRITICAL FUNCTIONS |
NC-2 | ADD TO BLACKLIST FUNCTION |
NC-3 | GENERATE PERFECT CODE HEADERS EVERY TIME |
NC-4 | COMMENTED CODE |
NC-5 | INCONSISTENT SOLIDITY VERSIONS |
NC-6 | IMPLEMENTATION CONTRACT MAY NOT BE INITIALIZED |
NC-7 | MARK VISIBILITY OF INITIALIZE(…) FUNCTIONS AS EXTERNAL |
NC-8 | DON’T WORRY ABOUT KECCAK256 COLLISIONS |
NC-9 | LACK OF EVENT EMISSION AFTER CRITICAL INITIALIZE() FUNCTIONS |
NC-10 | FOR EXTENDED “USING-FOR” USAGE, USE THE LATEST PRAGMA VERSION |
NC-11 | Omissions in events |
NC-12 | FOR FUNCTIONS AND VARIABLES FOLLOW SOLIDITY STANDARD NAMING CONVENTIONS |
NC-13 | Functions not used internally could be marked external |
It is a good practice to give time for users to react and adjust to critical changes. A timelock provides more guarantees and reduces the level of trust required, thus decreasing risk for users. It also indicates that the project is legitimate (less risk of a malicious owner making a sandwich attack on a user).
File: /contracts/LSP0ERC725Account/LSP0ERC725AccountCore.sol 339: function setData( 380: function setDataBatch( 875: function _setData(
File: /contracts/LSP4DigitalAssetMetadata/LSP4DigitalAssetMetadata.sol 52: function _setData(
File: /contracts/LSP4DigitalAssetMetadata/LSP4DigitalAssetMetadataInitAbstract.sol 50: function _setData(
File: /submodules/ERC725/implementations/contracts/ERC725YCore.sol 62: function setData( 73: function setDataBatch( 104: function _setData(
NFT thefts have increased recently, so with the addition of hacked NFTs to the platform, NFTs can be converted into liquidity. To prevent this, I recommend adding the blacklist function.
Add to Blacklist function and modifier.
I recommend using header for Solidity code layout and readability: https://github.com/transmissions11/headers
/*////////////////////////////////////////////////////////////// TESTING 123 //////////////////////////////////////////////////////////////*/
File: /contracts/LSP2ERC725YJSONSchema/LSP2Utils.sol 38: dataKey[dataKey.length - 2] == 0x5b && // "[" in utf8 encoded 39: dataKey[dataKey.length - 1] == 0x5d, // "]" in utf8
The project is compiled with different versions of Solidity, which is not recommended because it can lead to undefined behaviors.
It is better to use one Solidity compiler version across all contracts instead of different versions with different bugs and security checks.
File: /contracts/LSP0ERC725Account/ILSP0ERC725Account.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP0ERC725Account/LSP0Constants.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP0ERC725Account/LSP0ERC725Account.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP0ERC725Account/LSP0ERC725AccountCore.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP0ERC725Account/LSP0ERC725AccountInit.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP0ERC725Account/LSP0ERC725AccountInitAbstract.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP0ERC725Account/LSP0Utils.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP14Ownable2Step/ILSP14Ownable2Step.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP14Ownable2Step/LSP14Constants.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP14Ownable2Step/LSP14Errors.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP14Ownable2Step/LSP14Ownable2Step.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP17ContractExtension/LSP17Constants.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP17ContractExtension/LSP17Errors.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP17ContractExtension/LSP17Extendable.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP17ContractExtension/LSP17Extension.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP17ContractExtension/LSP17Utils.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP1UniversalReceiver/LSP1UniversalReceiverDelegateUP/LSP1UniversalReceiverDelegateUP.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP20CallVerification/ILSP20CallVerifier.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP20CallVerification/LSP20CallVerification.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP20CallVerification/LSP20Constants.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP20CallVerification/LSP20Errors.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP2ERC725YJSONSchema/LSP2Utils.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP4DigitalAssetMetadata/ILSP4Compatibility.sol 3: pragma solidity ^0.8.4;
File: /contracts/LSP4DigitalAssetMetadata/LSP4Compatibility.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP4DigitalAssetMetadata/LSP4Constants.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP4DigitalAssetMetadata/LSP4DigitalAssetMetadata.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP4DigitalAssetMetadata/LSP4DigitalAssetMetadataInitAbstract.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP4DigitalAssetMetadata/LSP4Errors.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP6KeyManager/LSP6Modules/LSP6ExecuteModule.sol 2: pragma solidity ^0.8.5;
File: /contracts/LSP6KeyManager/LSP6Modules/LSP6OwnershipModule.sol 2: pragma solidity ^0.8.5;
File: /contracts/LSP6KeyManager/LSP6Modules/LSP6SetDataModule.sol 2: pragma solidity ^0.8.5;
File: /contracts/LSP7DigitalAsset/ILSP7DigitalAsset.sol 3: pragma solidity ^0.8.4;
File: /contracts/LSP7DigitalAsset/LSP7Constants.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP7DigitalAsset/LSP7DigitalAsset.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP7DigitalAsset/LSP7DigitalAssetCore.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP7DigitalAsset/LSP7DigitalAssetInitAbstract.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP7DigitalAsset/LSP7Errors.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP8IdentifiableDigitalAsset/ILSP8IdentifiableDigitalAsset.sol 3: pragma solidity ^0.8.4;
File: /contracts/LSP8IdentifiableDigitalAsset/LSP8Constants.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP8IdentifiableDigitalAsset/LSP8Errors.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAsset.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAssetCore.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAssetInitAbstract.sol 2: pragma solidity ^0.8.4;
File: /contracts/UniversalProfile.sol 2: pragma solidity ^0.8.4;
File: /contracts/UniversalProfileInit.sol 2: pragma solidity ^0.8.4;
File: /contracts/UniversalProfileInitAbstract.sol 2: pragma solidity ^0.8.4;
File: /submodules/ERC725/implementations/contracts/ERC725.sol 2: pragma solidity ^0.8.0;
File: /submodules/ERC725/implementations/contracts/ERC725Init.sol 2: pragma solidity ^0.8.0;
File: /submodules/ERC725/implementations/contracts/ERC725InitAbstract.sol 2: pragma solidity ^0.8.0;
File: /submodules/ERC725/implementations/contracts/ERC725X.sol 2: pragma solidity ^0.8.0;
File: /submodules/ERC725/implementations/contracts/ERC725XCore.sol 2: pragma solidity ^0.8.0;
File: /submodules/ERC725/implementations/contracts/ERC725XInit.sol 2: pragma solidity ^0.8.0;
File: /submodules/ERC725/implementations/contracts/ERC725XInitAbstract.sol 2: pragma solidity ^0.8.0;
File: /submodules/ERC725/implementations/contracts/ERC725Y.sol 2: pragma solidity ^0.8.0;
File: /submodules/ERC725/implementations/contracts/ERC725YCore.sol 2: pragma solidity ^0.8.0;
File: /submodules/ERC725/implementations/contracts/ERC725YInit.sol 2: pragma solidity ^0.8.0;
File: /submodules/ERC725/implementations/contracts/ERC725YInitAbstract.sol 2: pragma solidity ^0.8.0;
File: /submodules/ERC725/implementations/contracts/constants.sol 2: pragma solidity ^0.8.0;
File: /submodules/ERC725/implementations/contracts/errors.sol 2: pragma solidity ^0.8.0;
OpenZeppelin recommends that the initializer modifier be applied to constructors.
Per OZs Post implementation contract should be initialized to avoid potential griefs or exploits.
https://forum.openzeppelin.com/t/uupsupgradeable-vulnerability-post-mortem/15680/5
File: /contracts/LSP0ERC725Account/LSP0ERC725AccountInitAbstract.sol 7: Initializable 8: } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; 45: Initializable,
File: /submodules/ERC725/implementations/contracts/ERC725InitAbstract.sol 7: Initializable 22: Initializable,
File: /submodules/ERC725/implementations/contracts/ERC725XInitAbstract.sol 6: Initializable
File: /submodules/ERC725/implementations/contracts/ERC725YInitAbstract.sol 6: Initializable
If someone wants to extend via inheritance, it might make more sense that the overridden initialize(...) function calls the internal {...}_init function, not the parent public initialize(...) function.
External instead of public would give more sense of the initialize(...) functions to behave like a constructor (only called on deployment, so should only be called externally).
From a security point of view, it might be safer so that it cannot be called internally by accident in the child contract.
File: /submodules/ERC725/implementations/contracts/ERC725Init.sol 27: function initialize(address newOwner) public payable virtual initializer {
File: /submodules/ERC725/implementations/contracts/ERC725XInit.sol 26: function initialize(address newOwner) public payable virtual initializer {
File: /submodules/ERC725/implementations/contracts/ERC725YInit.sol 26: function initialize(address newOwner) public payable virtual initializer {
File: /contracts/LSP6KeyManager/LSP6Modules/LSP6SetDataModule.sol 733: continue;
To record the init parameters for off-chain monitoring and transparency reasons, please consider emitting an event after the initialize() functions.
File: /contracts/LSP0ERC725Account/LSP0ERC725AccountInit.sol 62: function initialize(
File: /contracts/UniversalProfileInit.sol 34: function initialize(
File: /submodules/ERC725/implementations/contracts/ERC725Init.sol 27: function initialize(address newOwner) public payable virtual initializer {
File: /submodules/ERC725/implementations/contracts/ERC725XInit.sol 26: function initialize(address newOwner) public payable virtual initializer {
File: /submodules/ERC725/implementations/contracts/ERC725YInit.sol 26: function initialize(address newOwner) public payable virtual initializer {
File: /contracts/LSP0ERC725Account/ILSP0ERC725Account.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP0ERC725Account/LSP0Constants.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP0ERC725Account/LSP0ERC725Account.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP0ERC725Account/LSP0ERC725AccountCore.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP0ERC725Account/LSP0ERC725AccountInit.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP0ERC725Account/LSP0ERC725AccountInitAbstract.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP0ERC725Account/LSP0Utils.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP14Ownable2Step/ILSP14Ownable2Step.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP14Ownable2Step/LSP14Constants.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP14Ownable2Step/LSP14Errors.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP14Ownable2Step/LSP14Ownable2Step.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP17ContractExtension/LSP17Constants.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP17ContractExtension/LSP17Errors.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP17ContractExtension/LSP17Extendable.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP17ContractExtension/LSP17Extension.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP17ContractExtension/LSP17Utils.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP1UniversalReceiver/LSP1UniversalReceiverDelegateUP/LSP1UniversalReceiverDelegateUP.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP20CallVerification/ILSP20CallVerifier.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP20CallVerification/LSP20CallVerification.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP20CallVerification/LSP20Constants.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP20CallVerification/LSP20Errors.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP2ERC725YJSONSchema/LSP2Utils.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP4DigitalAssetMetadata/ILSP4Compatibility.sol 3: pragma solidity ^0.8.4;
File: /contracts/LSP4DigitalAssetMetadata/LSP4Compatibility.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP4DigitalAssetMetadata/LSP4Constants.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP4DigitalAssetMetadata/LSP4DigitalAssetMetadata.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP4DigitalAssetMetadata/LSP4DigitalAssetMetadataInitAbstract.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP4DigitalAssetMetadata/LSP4Errors.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP6KeyManager/LSP6Modules/LSP6ExecuteModule.sol 2: pragma solidity ^0.8.5;
File: /contracts/LSP6KeyManager/LSP6Modules/LSP6OwnershipModule.sol 2: pragma solidity ^0.8.5;
File: /contracts/LSP6KeyManager/LSP6Modules/LSP6SetDataModule.sol 2: pragma solidity ^0.8.5;
File: /contracts/LSP7DigitalAsset/ILSP7DigitalAsset.sol 3: pragma solidity ^0.8.4;
File: /contracts/LSP7DigitalAsset/LSP7Constants.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP7DigitalAsset/LSP7DigitalAsset.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP7DigitalAsset/LSP7DigitalAssetCore.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP7DigitalAsset/LSP7DigitalAssetInitAbstract.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP7DigitalAsset/LSP7Errors.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP8IdentifiableDigitalAsset/ILSP8IdentifiableDigitalAsset.sol 3: pragma solidity ^0.8.4;
File: /contracts/LSP8IdentifiableDigitalAsset/LSP8Constants.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP8IdentifiableDigitalAsset/LSP8Errors.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAsset.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAssetCore.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAssetInitAbstract.sol 2: pragma solidity ^0.8.4;
File: /contracts/UniversalProfile.sol 2: pragma solidity ^0.8.4;
File: /contracts/UniversalProfileInit.sol 2: pragma solidity ^0.8.4;
File: /contracts/UniversalProfileInitAbstract.sol 2: pragma solidity ^0.8.4;
File: /submodules/ERC725/implementations/contracts/ERC725.sol 2: pragma solidity ^0.8.0;
File: /submodules/ERC725/implementations/contracts/ERC725Init.sol 2: pragma solidity ^0.8.0;
File: /submodules/ERC725/implementations/contracts/ERC725InitAbstract.sol 2: pragma solidity ^0.8.0;
File: /submodules/ERC725/implementations/contracts/ERC725X.sol 2: pragma solidity ^0.8.0;
File: /submodules/ERC725/implementations/contracts/ERC725XCore.sol 2: pragma solidity ^0.8.0;
File: /submodules/ERC725/implementations/contracts/ERC725XInit.sol 2: pragma solidity ^0.8.0;
File: /submodules/ERC725/implementations/contracts/ERC725XInitAbstract.sol 2: pragma solidity ^0.8.0;
File: /submodules/ERC725/implementations/contracts/ERC725Y.sol 2: pragma solidity ^0.8.0;
File: /submodules/ERC725/implementations/contracts/ERC725YCore.sol 2: pragma solidity ^0.8.0;
File: /submodules/ERC725/implementations/contracts/ERC725YInit.sol 2: pragma solidity ^0.8.0;
File: /submodules/ERC725/implementations/contracts/ERC725YInitAbstract.sol 2: pragma solidity ^0.8.0;
File: /submodules/ERC725/implementations/contracts/constants.sol 2: pragma solidity ^0.8.0;
File: /submodules/ERC725/implementations/contracts/errors.sol 2: pragma solidity ^0.8.0;
Use solidity pragma version min. 0.8.13
Throughout the codebase, events are generally emitted when sensitive changes are made to the contracts. However, some events are missing important parameters.
File: /contracts/LSP14Ownable2Step/LSP14Ownable2Step.sol 165: emit RenounceOwnershipStarted(); 178: emit OwnershipRenounced();
Solidity’s standard naming convention for internal and private functions and variables (apart from constants): the mixedCase format starting with an underscore (_mixedCase starting with an underscore)
Solidity’s standard naming convention for internal and private constants variables: the snake_case format starting with an underscore (_mixedCase starting with an underscore) and use ALL_CAPS for naming them.
File: /contracts/LSP2ERC725YJSONSchema/LSP2Utils.sol 231: function isEncodedArray(bytes memory data) internal pure returns (bool) {
File: /contracts/LSP0ERC725Account/LSP0ERC725AccountCore.sol 171: function batchCalls(
Issue | |
---|---|
L-1 | Initializing state-variables in proxy-based upgradeable contracts |
L-2 | CRITICAL CHANGES SHOULD USE TWO-STEP PROCEDURE |
L-3 | UNIFY RETURN CRITERIA |
L-4 | TOKEN SHOULD THROW AN ERROR IF _TOKENID IS NOT A VALID NFT |
This should be done in initializer functions and not as part of the state variable declarations in which case they won’t be set.
File: /contracts/LSP0ERC725Account/LSP0ERC725AccountInit.sol 62: function initialize(
File: /contracts/UniversalProfileInit.sol 34: function initialize(
File: /submodules/ERC725/implementations/contracts/ERC725Init.sol 27: function initialize(address newOwner) public payable virtual initializer {
File: /submodules/ERC725/implementations/contracts/ERC725XInit.sol 26: function initialize(address newOwner) public payable virtual initializer {
File: /submodules/ERC725/implementations/contracts/ERC725YInit.sol 26: function initialize(address newOwner) public payable virtual initializer {
The critical procedures should be two step process.
File: /contracts/LSP4DigitalAssetMetadata/LSP4DigitalAssetMetadata.sol 52: function _setData(
File: /contracts/LSP4DigitalAssetMetadata/LSP4DigitalAssetMetadataInitAbstract.sol 50: function _setData(
File: /contracts/LSP6KeyManager/LSP6Modules/LSP6OwnershipModule.sol 14: function _verifyOwnershipPermissions(
File: /submodules/ERC725/implementations/contracts/ERC725YCore.sol 62: function setData( 73: function setDataBatch( 104: function _setData(
Lack of two-step procedure for critical operations leaves them error-prone. Consider adding two step procedure on the critical functions.
In contracts, sometimes the name of the return variable is not defined and sometimes is, unifying the way of writing the code makes the code more uniform and readable.
File: /contracts/LSP0ERC725Account/ILSP0ERC725Account.sol 69: ) external returns (bytes[] memory results);
File: /contracts/LSP0ERC725Account/LSP0ERC725AccountCore.sol 173: ) public returns (bytes[] memory results) { 227: ) public payable virtual override returns (bytes memory) { 285: ) public payable virtual override returns (bytes[] memory) { 463: ) public payable virtual returns (bytes memory returnedValues) { 699: returns (bool) 737: ) public view virtual returns (bytes4 magicValue) { 853: ) internal view virtual override returns (address) {
File: /contracts/LSP0ERC725Account/LSP0Utils.sol 26: ) internal view returns (bytes memory) { 40: ) internal view returns (bytes memory) {
File: /contracts/LSP14Ownable2Step/ILSP14Ownable2Step.sol 42: function pendingOwner() external view returns (address);
File: /contracts/LSP14Ownable2Step/LSP14Ownable2Step.sol 59: function pendingOwner() public view virtual returns (address) {
File: /contracts/LSP17ContractExtension/LSP17Extendable.sol 30: ) public view virtual override returns (bool) { 46: ) internal view virtual returns (bool) { 67: ) internal view virtual returns (address);
File: /contracts/LSP17ContractExtension/LSP17Extension.sol 22: ) public view virtual override returns (bool) { 36: returns (bytes calldata) 44: function _extendableMsgSender() internal view virtual returns (address) { 54: function _extendableMsgValue() internal view virtual returns (uint256) {
File: /contracts/LSP17ContractExtension/LSP17Utils.sol 16: ) internal pure returns (bool) {
File: /contracts/LSP1UniversalReceiver/LSP1UniversalReceiverDelegateUP/LSP1UniversalReceiverDelegateUP.sol 81: ) public payable virtual returns (bytes memory result) { 157: ) internal virtual returns (bytes memory) { 206: ) internal virtual returns (bytes memory) { 261: ) public view virtual override returns (bool) {
File: /contracts/LSP20CallVerification/ILSP20CallVerifier.sol 23: ) external returns (bytes4 magicValue); 34: ) external returns (bytes4);
File: /contracts/LSP20CallVerification/LSP20CallVerification.sol 25: ) internal virtual returns (bool verifyAfter) {
File: /contracts/LSP2ERC725YJSONSchema/LSP2Utils.sol 24: ) internal pure returns (bytes32) { 34: ) internal pure returns (bytes32) { 55: ) internal pure returns (bytes32) { 74: ) internal pure returns (bytes32) { 97: ) internal pure returns (bytes32) { 118: ) internal pure returns (bytes32) { 140: ) internal pure returns (bytes32) { 165: ) internal pure returns (bytes32) { 184: ) internal pure returns (bytes32) { 203: ) internal pure returns (bytes memory) { 220: ) internal pure returns (bytes memory) { 231: function isEncodedArray(bytes memory data) internal pure returns (bool) { 253: ) internal pure returns (bool) { 285: ) internal pure returns (bool) { 314: ) internal pure returns (bool) {
File: /contracts/LSP4DigitalAssetMetadata/ILSP4Compatibility.sol 18: function name() external view returns (string memory); 24: function symbol() external view returns (string memory);
File: /contracts/LSP4DigitalAssetMetadata/LSP4Compatibility.sol 25: function name() public view virtual override returns (string memory) { 34: function symbol() public view virtual override returns (string memory) {
File: /contracts/LSP6KeyManager/LSP6Modules/LSP6ExecuteModule.sol 321: ) internal pure returns (bytes4 requiredCallTypes) { 341: ) internal pure returns (uint256, address, uint256, bytes4, bool) { 369: ) internal pure returns (bool) { 385: ) internal view returns (bool) { 402: ) internal pure returns (bool) { 421: ) internal pure returns (bool) {
File: /contracts/LSP6KeyManager/LSP6Modules/LSP6SetDataModule.sol 195: ) internal view virtual returns (bytes32) { 339: ) internal view virtual returns (bytes32) { 388: ) internal view virtual returns (bytes32) { 411: ) internal view virtual returns (bytes32) { 443: ) internal view returns (bytes32) { 477: ) internal view virtual returns (bytes32) { 493: ) internal view virtual returns (bytes32) {
File: /contracts/LSP7DigitalAsset/ILSP7DigitalAsset.sol 65: function decimals() external view returns (uint8); 71: function totalSupply() external view returns (uint256); 80: function balanceOf(address tokenOwner) external view returns (uint256); 134: ) external view returns (uint256);
File: /contracts/LSP7DigitalAsset/LSP7DigitalAsset.sol 53: ) public view virtual override(IERC165, ERC725YCore) returns (bool) {
File: /contracts/LSP7DigitalAsset/LSP7DigitalAssetCore.sol 54: function decimals() public view virtual returns (uint8) { 61: function totalSupply() public view virtual returns (uint256) { 72: ) public view virtual returns (uint256) { 111: ) public view virtual returns (uint256) {
File: /contracts/LSP7DigitalAsset/LSP7DigitalAssetInitAbstract.sol 47: ) public view virtual override(IERC165, ERC725YCore) returns (bool) {
File: /contracts/LSP8IdentifiableDigitalAsset/ILSP8IdentifiableDigitalAsset.sol 66: function totalSupply() external view returns (uint256); 77: function balanceOf(address tokenOwner) external view returns (uint256); 88: function tokenOwnerOf(bytes32 tokenId) external view returns (address); 97: ) external view returns (bytes32[] memory); 150: ) external view returns (bool); 163: ) external view returns (address[] memory);
File: /contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAsset.sol 47: ) public view virtual override(IERC165, ERC725YCore) returns (bool) {
File: /contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAssetCore.sol 61: function totalSupply() public view virtual returns (uint256) { 72: ) public view virtual returns (uint256) { 81: ) public view virtual returns (address) { 96: ) public view virtual returns (bytes32[] memory) { 156: ) public view virtual returns (bool) { 167: ) public view virtual returns (address[] memory) { 180: ) internal view virtual returns (bool) { 290: function _exists(bytes32 tokenId) internal view virtual returns (bool) {
File: /contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAssetInitAbstract.sol 47: ) public view virtual override(IERC165, ERC725YCore) returns (bool) {
File: /submodules/ERC725/implementations/contracts/ERC725.sol 39: ) public view virtual override(ERC725XCore, ERC725YCore) returns (bool) {
File: /submodules/ERC725/implementations/contracts/ERC725InitAbstract.sol 41: ) public view virtual override(ERC725XCore, ERC725YCore) returns (bool) {
File: /submodules/ERC725/implementations/contracts/ERC725XCore.sol 45: ) public payable virtual override onlyOwner returns (bytes memory) { 57: ) public payable virtual override onlyOwner returns (bytes[] memory) { 66: ) public view virtual override(IERC165, ERC165) returns (bool) { 81: ) internal virtual returns (bytes memory) { 136: ) internal virtual returns (bytes[] memory) { 178: ) internal virtual returns (bytes memory result) { 206: ) internal virtual returns (bytes memory result) { 228: ) internal virtual returns (bytes memory result) { 250: ) internal virtual returns (bytes memory newContract) { 291: ) internal virtual returns (bytes memory newContract) {
File: /submodules/ERC725/implementations/contracts/ERC725YCore.sol 35: ) public view virtual override returns (bytes memory dataValue) { 44: ) public view virtual override returns (bytes[] memory dataValues) { 100: ) internal view virtual returns (bytes memory dataValue) { 117: ) public view virtual override(IERC165, ERC165) returns (bool) {
add {return x}
if you want to return the updated value or else remove returns(uint)
from the function(){}
if no value you wanted to return
File: /contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAssetCore.sol 54: mapping(address => EnumerableSet.Bytes32Set) private _tokenIdsForOperator;
Consider throwing an error if _tokenId is not a valid NFT.
#0 - c4-judge
2023-08-02T09:28:40Z
trust1995 marked the issue as grade-b
🌟 Selected for report: Raihan
Also found by: DavidGiladi, LeoS, Rageur, ReyAdmirado, Rolezn, SAAJ, SAQ, SM3_SS, Sathish9098, hunter_w3b, matrix_0wl, naman1778, petrichor
33.4768 USDC - $33.48
Issue | |
---|---|
GAS-1 | Use selfbalance() instead of address(this).balance |
GAS-2 | ABI.ENCODE() IS LESS EFFICIENT THAN ABI.ENCODEPACKED() |
GAS-3 | Use assembly to check for address(0) |
GAS-4 | BEFORE SOME FUNCTIONS, WE SHOULD CHECK SOME VARIABLES FOR POSSIBLE GAS SAVE |
GAS-5 | USING CALLDATA INSTEAD OF MEMORY FOR READ-ONLY ARGUMENTS IN EXTERNAL FUNCTIONS SAVES GAS |
GAS-5 | Setting the constructor to payable |
GAS-7 | INTERNAL FUNCTIONS NOT CALLED BY THE CONTRACT SHOULD BE REMOVED TO SAVE DEPLOYMENT GAS |
GAS-8 | MAKING CONSTANT VARIABLES PRIVATE WILL SAVE GAS DURING DEPLOYMENT |
GAS-9 | SAVE GAS BY NOT REQURING NON-ZERO INTERVAL IF NO LINEAR AMOUNT |
GAS-10 | The increment in for loop postcondition can be made unchecked |
GAS-11 | Use a more recent version of solidity |
GAS-12 | TERNARY OPERATION IS CHEAPER THAN IF-ELSE STATEMENT |
GAS-13 | Usage of uint /int smaller than 32 bytes (256 bits) incurs overhead |
GAS-14 | Use != 0 instead of > 0 for unsigned integer comparison |
GAS-15 | USE BYTES32 INSTEAD OF STRING |
GAS-16 | Public functions not called by the contract should be declared external instead OR Functions not used internally could be marked external |
selfbalance()
instead of address(this).balance
You can use selfbalance()
instead of address(this).balance
when getting your contract's balance of ETH to save gas.
Additionally, you can use balance(address)
instead of address.balance()
when getting an external contract's balance of ETH.
File: /submodules/ERC725/implementations/contracts/ERC725XCore.sol 179: if (address(this).balance < value) { 180: revert ERC725X_InsufficientBalance(address(this).balance, value); 251: if (address(this).balance < value) { 252: revert ERC725X_InsufficientBalance(address(this).balance, value);
ABI.ENCODE()
IS LESS EFFICIENT THAN ABI.ENCODEPACKED()
Use abi.encodePacked()
where possible to save gas
File: /contracts/LSP0ERC725Account/LSP0ERC725AccountCore.sol 253: LSP20CallVerification._verifyCallResult(_owner, abi.encode(result)); 319: abi.encode(results)
address(0)
File: /contracts/LSP0ERC725Account/LSP0ERC725AccountCore.sol 801: if (msg.sig == bytes4(0) && extension == address(0)) return; 801: if (msg.sig == bytes4(0) && extension == address(0)) return; 804: if (extension == address(0))
File: /contracts/LSP17ContractExtension/LSP17Extendable.sol 50: if (erc165Extension == address(0)) return false; 91: if (extension == address(0))
File: /contracts/LSP1UniversalReceiver/LSP1UniversalReceiverDelegateUP/LSP1UniversalReceiverDelegateUP.sol 116: bool isMapValueSet = bytes20(notifierMapValue) != bytes20(0);
File: /contracts/LSP20CallVerification/LSP20CallVerification.sol 80: bytes28(bytes32(returnedData) << 32) != bytes28(0)
File: /contracts/LSP2ERC725YJSONSchema/LSP2Utils.sol 266: if (bytes12(key) != bytes12(0)) return false;
File: /contracts/LSP6KeyManager/LSP6Modules/LSP6ExecuteModule.sol 345: if (bytes12(executeCalldata[36:48]) != bytes12(0)) { 410: bool isFunctionCall = requiredFunction != bytes4(0);
File: /contracts/LSP6KeyManager/LSP6Modules/LSP6SetDataModule.sol 97: if (requiredPermission == bytes32(0)) return; 146: if (requiredPermission != bytes32(0)) { 392: bytes32(
File: /contracts/LSP7DigitalAsset/LSP7DigitalAssetCore.sol 268: if (operator == address(0)) { 300: if (to == address(0)) { 343: if (from == address(0)) { 406: if (from == address(0) || to == address(0)) { 406: if (from == address(0) || to == address(0)) {
File: /contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAssetCore.sol 84: if (tokenOwner == address(0)) { 115: if (operator == address(0)) { 139: if (operator == address(0)) { 291: return _tokenOwners[tokenId] != address(0); 319: if (to == address(0)) { 410: if (to == address(0)) {
File: /submodules/ERC725/implementations/contracts/ERC725.sol 28: newOwner != address(0),
File: /submodules/ERC725/implementations/contracts/ERC725InitAbstract.sol 28: newOwner != address(0),
File: /submodules/ERC725/implementations/contracts/ERC725X.sol 22: newOwner != address(0),
File: /submodules/ERC725/implementations/contracts/ERC725XCore.sol 89: if (target != address(0)) 96: if (target != address(0)) 269: if (contractAddress == address(0)) {
File: /submodules/ERC725/implementations/contracts/ERC725XInitAbstract.sol 21: newOwner != address(0),
File: /submodules/ERC725/implementations/contracts/ERC725Y.sol 23: newOwner != address(0),
File: /submodules/ERC725/implementations/contracts/ERC725YInitAbstract.sol 21: newOwner != address(0),
Before transfer, we should check for amount being 0 so the function doesnt run when its not gonna do anything:
File: /contracts/LSP0ERC725Account/LSP0ERC725AccountCore.sol 557: function transferOwnership( 565: LSP14Ownable2Step._transferOwnership(pendingNewOwner); 586: LSP14Ownable2Step._transferOwnership(pendingNewOwner);
File: /contracts/LSP14Ownable2Step/ILSP14Ownable2Step.sol 54: function transferOwnership(address newOwner) external;
File: /contracts/LSP14Ownable2Step/LSP14Ownable2Step.sol 66: function transferOwnership( 69: _transferOwnership(newOwner); 126: function _transferOwnership(address newOwner) internal virtual {
File: /contracts/LSP7DigitalAsset/ILSP7DigitalAsset.sol 159: function transfer( 189: function transferBatch(
File: /contracts/LSP7DigitalAsset/LSP7DigitalAssetCore.sol 124: function transfer( 148: _transfer(from, to, amount, allowNonLSP1Recipient, data); 154: function transferBatch( 173: transfer( 399: function _transfer(
File: /contracts/LSP8IdentifiableDigitalAsset/ILSP8IdentifiableDigitalAsset.sol 186: function transfer( 216: function transferBatch(
File: /contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAssetCore.sol 191: function transfer( 204: _transfer(from, to, tokenId, allowNonLSP1Recipient, data); 210: function transferBatch( 228: transfer( 394: function _transfer(
Mark data types as calldata
instead of memory
where possible. This makes it so that the data is not automatically loaded into memory. If the data passed into the function does not need to be changed (like updating values in an array), it can be passed in as calldata
. The one exception to this is if the argument must later be passed into another function that takes an argument that specifies memory
storage.
Source
Source 2
File: /contracts/LSP0ERC725Account/LSP0ERC725AccountCore.sol 226: bytes memory data 281: uint256[] memory operationsType, 282: address[] memory targets, 283: uint256[] memory values, 284: bytes[] memory datas 341: bytes memory dataValue 381: bytes32[] memory dataKeys, 382: bytes[] memory dataValues 736: bytes memory signature
File: /contracts/LSP1UniversalReceiver/LSP1UniversalReceiverDelegateUP/LSP1UniversalReceiverDelegateUP.sol 80: bytes memory /* data */
File: /contracts/LSP20CallVerification/ILSP20CallVerifier.sol 22: bytes memory receivedCalldata 33: bytes memory result
File: /contracts/LSP7DigitalAsset/ILSP7DigitalAsset.sol 164: bytes memory data 190: address[] memory from, 191: address[] memory to, 192: uint256[] memory amount, 193: bool[] memory allowNonLSP1Recipient, 194: bytes[] memory data
File: /contracts/LSP7DigitalAsset/LSP7DigitalAssetCore.sol 129: bytes memory data 155: address[] memory from, 156: address[] memory to, 157: uint256[] memory amount, 158: bool[] memory allowNonLSP1Recipient, 159: bytes[] memory data
File: /contracts/LSP8IdentifiableDigitalAsset/ILSP8IdentifiableDigitalAsset.sol 191: bytes memory data 217: address[] memory from, 218: address[] memory to, 219: bytes32[] memory tokenId, 220: bool[] memory allowNonLSP1Recipient, 221: bytes[] memory data
File: /contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAssetCore.sol 196: bytes memory data 211: address[] memory from, 212: address[] memory to, 213: bytes32[] memory tokenId, 214: bool[] memory allowNonLSP1Recipient, 215: bytes[] memory data
File: /submodules/ERC725/implementations/contracts/ERC725XCore.sol 44: bytes memory data 53: uint256[] memory operationsType, 54: address[] memory targets, 55: uint256[] memory values, 56: bytes[] memory datas
File: /submodules/ERC725/implementations/contracts/ERC725YCore.sol 43: bytes32[] memory dataKeys 64: bytes memory dataValue 74: bytes32[] memory dataKeys, 75: bytes[] memory dataValues
Saves ~13 gas per instance
File: /contracts/LSP0ERC725Account/LSP0ERC725AccountInit.sol 47: constructor() {
File: /contracts/LSP4DigitalAssetMetadata/LSP4DigitalAssetMetadata.sol 31: constructor(
File: /contracts/LSP7DigitalAsset/LSP7DigitalAsset.sol 39: constructor(
File: /contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAsset.sol 36: constructor(
File: /contracts/UniversalProfileInit.sol 19: constructor() {
File: /submodules/ERC725/implementations/contracts/ERC725Init.sol 19: constructor() {
File: /submodules/ERC725/implementations/contracts/ERC725XInit.sol 18: constructor() {
File: /submodules/ERC725/implementations/contracts/ERC725YInit.sol 18: constructor() {
If the functions are required by an interface, the contract should inherit from that interface and use the override keyword
File: /contracts/LSP17ContractExtension/LSP17Extendable.sol 86: function _fallbackLSP17Extendable() internal virtual {
File: /contracts/LSP17ContractExtension/LSP17Extension.sol 44: function _extendableMsgSender() internal view virtual returns (address) { 54: function _extendableMsgValue() internal view virtual returns (uint256) {
File: /contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAssetCore.sol 359: function _burn(bytes32 tokenId, bytes memory data) internal virtual {
File: /submodules/ERC725/implementations/contracts/ERC725InitAbstract.sol 26: function _initialize(address newOwner) internal virtual onlyInitializing {
File: /submodules/ERC725/implementations/contracts/ERC725XInitAbstract.sol 19: function _initialize(address newOwner) internal virtual onlyInitializing {
File: /submodules/ERC725/implementations/contracts/ERC725YInitAbstract.sol 19: function _initialize(address newOwner) internal virtual onlyInitializing {
When constants are marked public, extra getter functions are created, increasing the deployment cost. Marking these functions private will decrease gas cost. One can still read these variables through the source code. If they need to be accessed by an external contract, a separate single getter function can be used to return all constants as a tuple. There are four instances of public constants.
File: /contracts/LSP14Ownable2Step/LSP14Ownable2Step.sol 39: uint256 public constant RENOUNCE_OWNERSHIP_CONFIRMATION_DELAY = 200; 44: uint256 public constant RENOUNCE_OWNERSHIP_CONFIRMATION_PERIOD = 200;
If there is no linear amount, a Gsset for the claim’s interval can be converted to a Gsreset, saving 17100 gas.
File: /contracts/LSP14Ownable2Step/LSP14Errors.sol 7: error NotInRenounceOwnershipInterval(
File: /contracts/LSP14Ownable2Step/LSP14Ownable2Step.sol 170: revert NotInRenounceOwnershipInterval(
This is only relevant if you are using the default solidity checked arithmetic.
the for loop postcondition, i.e., i++
involves checked arithmetic, which is not required. This is because the value of i is always strictly less than length <= 2**256 - 1
. Therefore, the theoretical maximum value of i to enter the for-loop body is 2**256 - 2
. This means that the i++
in the for loop can never overflow. Regardless, the overflow checks are performed by the compiler.
Unfortunately, the Solidity optimizer is not smart enough to detect this and remove the checks.One can manually do this.
File: /contracts/LSP6KeyManager/LSP6Modules/LSP6SetDataModule.sol 156: inputDataKeysAllowed++; 743: allowedDataKeysFound++; 771: jj++;
File: /contracts/LSP0ERC725Account/ILSP0ERC725Account.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP0ERC725Account/LSP0Constants.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP0ERC725Account/LSP0ERC725Account.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP0ERC725Account/LSP0ERC725AccountCore.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP0ERC725Account/LSP0ERC725AccountInit.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP0ERC725Account/LSP0ERC725AccountInitAbstract.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP0ERC725Account/LSP0Utils.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP14Ownable2Step/ILSP14Ownable2Step.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP14Ownable2Step/LSP14Constants.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP14Ownable2Step/LSP14Errors.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP14Ownable2Step/LSP14Ownable2Step.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP17ContractExtension/LSP17Constants.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP17ContractExtension/LSP17Errors.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP17ContractExtension/LSP17Extendable.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP17ContractExtension/LSP17Extension.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP17ContractExtension/LSP17Utils.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP1UniversalReceiver/LSP1UniversalReceiverDelegateUP/LSP1UniversalReceiverDelegateUP.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP20CallVerification/ILSP20CallVerifier.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP20CallVerification/LSP20CallVerification.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP20CallVerification/LSP20Constants.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP20CallVerification/LSP20Errors.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP2ERC725YJSONSchema/LSP2Utils.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP4DigitalAssetMetadata/ILSP4Compatibility.sol 3: pragma solidity ^0.8.4;
File: /contracts/LSP4DigitalAssetMetadata/LSP4Compatibility.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP4DigitalAssetMetadata/LSP4Constants.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP4DigitalAssetMetadata/LSP4DigitalAssetMetadata.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP4DigitalAssetMetadata/LSP4DigitalAssetMetadataInitAbstract.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP4DigitalAssetMetadata/LSP4Errors.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP6KeyManager/LSP6Modules/LSP6ExecuteModule.sol 2: pragma solidity ^0.8.5;
File: /contracts/LSP6KeyManager/LSP6Modules/LSP6OwnershipModule.sol 2: pragma solidity ^0.8.5;
File: /contracts/LSP6KeyManager/LSP6Modules/LSP6SetDataModule.sol 2: pragma solidity ^0.8.5;
File: /contracts/LSP7DigitalAsset/ILSP7DigitalAsset.sol 3: pragma solidity ^0.8.4;
File: /contracts/LSP7DigitalAsset/LSP7Constants.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP7DigitalAsset/LSP7DigitalAsset.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP7DigitalAsset/LSP7DigitalAssetCore.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP7DigitalAsset/LSP7DigitalAssetInitAbstract.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP7DigitalAsset/LSP7Errors.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP8IdentifiableDigitalAsset/ILSP8IdentifiableDigitalAsset.sol 3: pragma solidity ^0.8.4;
File: /contracts/LSP8IdentifiableDigitalAsset/LSP8Constants.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP8IdentifiableDigitalAsset/LSP8Errors.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAsset.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAssetCore.sol 2: pragma solidity ^0.8.4;
File: /contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAssetInitAbstract.sol 2: pragma solidity ^0.8.4;
File: /contracts/UniversalProfile.sol 2: pragma solidity ^0.8.4;
File: /contracts/UniversalProfileInit.sol 2: pragma solidity ^0.8.4;
File: /contracts/UniversalProfileInitAbstract.sol 2: pragma solidity ^0.8.4;
File: /submodules/ERC725/implementations/contracts/ERC725.sol 2: pragma solidity ^0.8.0;
File: /submodules/ERC725/implementations/contracts/ERC725Init.sol 2: pragma solidity ^0.8.0;
File: /submodules/ERC725/implementations/contracts/ERC725InitAbstract.sol 2: pragma solidity ^0.8.0;
File: /submodules/ERC725/implementations/contracts/ERC725X.sol 2: pragma solidity ^0.8.0;
File: /submodules/ERC725/implementations/contracts/ERC725XCore.sol 2: pragma solidity ^0.8.0;
File: /submodules/ERC725/implementations/contracts/ERC725XInit.sol 2: pragma solidity ^0.8.0;
File: /submodules/ERC725/implementations/contracts/ERC725XInitAbstract.sol 2: pragma solidity ^0.8.0;
File: /submodules/ERC725/implementations/contracts/ERC725Y.sol 2: pragma solidity ^0.8.0;
File: /submodules/ERC725/implementations/contracts/ERC725YCore.sol 2: pragma solidity ^0.8.0;
File: /submodules/ERC725/implementations/contracts/ERC725YInit.sol 2: pragma solidity ^0.8.0;
File: /submodules/ERC725/implementations/contracts/ERC725YInitAbstract.sol 2: pragma solidity ^0.8.0;
File: /submodules/ERC725/implementations/contracts/constants.sol 2: pragma solidity ^0.8.0;
File: /submodules/ERC725/implementations/contracts/errors.sol 2: pragma solidity ^0.8.0;
There are instances where a ternary operation can be used instead of if-else statement. In these cases, using ternary operation will save modest amounts of gas. Note that this optimization seems to be dependent on usage of a more recent Solidity version. The following gas savings are on version 0.8.17.
File: /contracts/LSP7DigitalAsset/LSP7DigitalAssetCore.sol 112: if (tokenOwner == operator) { return _tokenOwnerBalances[tokenOwner]; } else { return _operatorAuthorizedAmount[tokenOwner][operator]; } 278: if (amount != 0) { emit AuthorizedOperator(operator, tokenOwner, amount); } else { emit RevokedOperator(operator, tokenOwner); } 491: if (to.code.length > 0) { revert LSP7NotifyTokenReceiverContractMissingLSP1Interface(to); } else { revert LSP7NotifyTokenReceiverIsEOA(to); }
File: /contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAssetCore.sol 493: if (to.code.length > 0) { revert LSP8NotifyTokenReceiverContractMissingLSP1Interface(to); } else { revert LSP8NotifyTokenReceiverIsEOA(to); }
uint
/int
smaller than 32 bytes (256 bits) incurs overheadWhen using elements that are smaller than 32 bytes, your contract’s gas usage may be higher. This is because the EVM operates on 32 bytes at a time. Therefore, if the element is smaller than that, the EVM must use more operations in order to reduce the size of the element from 32 bytes to the desired size.
Each operation involving a uint8
costs an extra 22-28 gas (depending on whether the other operand is also a variable of type uint8
) as compared to ones involving uint256, due to the compiler having to clear the higher bits of the memory word before operating on the uint8, as well as the associated stack operations of doing so. Use a larger size then downcast where needed.
https://docs.soliditylang.org/en/v0.8.11/internals/layout_in_storage.html
Use a larger size then downcast where needed.
File: /contracts/LSP2ERC725YJSONSchema/LSP2Utils.sol 336: uint256 elementLength = uint16(
File: /contracts/LSP6KeyManager/LSP6Modules/LSP6ExecuteModule.sol 395: allowedStandard == bytes4(type(uint32).max) || 414: allowedFunction == bytes4(type(uint32).max) ||
File: /contracts/LSP6KeyManager/LSP6Modules/LSP6SetDataModule.sol 544: length = uint16( 664: length = uint16(
File: /contracts/LSP7DigitalAsset/ILSP7DigitalAsset.sol 65: function decimals() external view returns (uint8);
File: /contracts/LSP7DigitalAsset/LSP7DigitalAssetCore.sol 54: function decimals() public view virtual returns (uint8) {
To update this with using at least 0.8.6 there is no difference in gas usage with!= 0 or > 0. Source
File: /contracts/LSP0ERC725Account/LSP0ERC725AccountCore.sol 182: if (result.length > 0) { 741: if (_owner.code.length > 0) {
File: /contracts/LSP1UniversalReceiver/LSP1UniversalReceiverDelegateUP/LSP1UniversalReceiverDelegateUP.sol 165: if (notifier.code.length > 0) {
File: /contracts/LSP20CallVerification/LSP20CallVerification.sol 86: if (returnedData.length > 0) {
File: /contracts/LSP7DigitalAsset/LSP7DigitalAssetCore.sol 491: if (to.code.length > 0) {
File: /contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAssetCore.sol 493: if (to.code.length > 0) {
Use bytes32 instead of string to save gas whenever possible. String is a dynamic data structure and therefore is more gas consuming then bytes32.
File: /contracts/LSP2ERC725YJSONSchema/LSP2Utils.sol 23: string memory keyName 33: string memory keyName 72: string memory firstWord, 73: string memory lastWord 95: string memory firstWord, 137: string memory firstWord, 138: string memory secondWord, 200: string memory hashFunction, 201: string memory json, 202: string memory url 217: string memory hashFunction, 218: string memory assetBytes, 219: string memory url
File: /contracts/LSP4DigitalAssetMetadata/ILSP4Compatibility.sol 18: function name() external view returns (string memory); 24: function symbol() external view returns (string memory);
File: /contracts/LSP4DigitalAssetMetadata/LSP4Compatibility.sol 25: function name() public view virtual override returns (string memory) { 27: return string(data); 34: function symbol() public view virtual override returns (string memory) { 36: return string(data);
File: /contracts/LSP4DigitalAssetMetadata/LSP4DigitalAssetMetadata.sol 32: string memory name_, 33: string memory symbol_,
File: /contracts/LSP4DigitalAssetMetadata/LSP4DigitalAssetMetadataInitAbstract.sol 28: string memory name_, 29: string memory symbol_,
File: /contracts/LSP6KeyManager/LSP6Modules/LSP6ExecuteModule.sol 445: string memory permissionErrorString = LSP6Utils.getPermissionName(
File: /contracts/LSP6KeyManager/LSP6Modules/LSP6OwnershipModule.sol 24: string memory permissionErrorString = LSP6Utils.getPermissionName(
File: /contracts/LSP6KeyManager/LSP6Modules/LSP6SetDataModule.sol 788: string memory permissionErrorString = LSP6Utils.getPermissionName(
File: /contracts/LSP7DigitalAsset/LSP7DigitalAsset.sol 40: string memory name_, 41: string memory symbol_,
File: /contracts/LSP7DigitalAsset/LSP7DigitalAssetInitAbstract.sol 29: string memory name_, 30: string memory symbol_,
File: /contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAsset.sol 37: string memory name_, 38: string memory symbol_,
File: /contracts/LSP8IdentifiableDigitalAsset/LSP8IdentifiableDigitalAssetInitAbstract.sol 31: string memory name_, 32: string memory symbol_,
Contracts are allowed to override their parents’ functions and change the visibility from external to public and can save gas by doing so.
File: /contracts/LSP0ERC725Account/LSP0ERC725AccountCore.sol 171: function batchCalls(
#0 - c4-judge
2023-08-02T09:11:20Z
trust1995 marked the issue as grade-b