code-423n4 / 2022-03-joyn-findings

4 stars 1 forks source link

Gas Optimizations #125

Open code423n4 opened 2 years ago

code423n4 commented 2 years ago

2022-03-joyn gas optimization

1 Use initial value for string. You set default value for HASHED_PROOF. To save deployment gas cost you can use initial value for string.

https://github.com/code-423n4/2022-03-joyn/blob/main/core-contracts/contracts/CoreCollection.sol#L27

string public HASHED_PROOF;

Avg deployment from 3070877 to 3067973 with this change

2 modifier onlyValidSupply used only one time in the contract. modifier onlyValidSupply is used only in initialize, so you can write this require statement directly in the function to save gas.

https://github.com/code-423n4/2022-03-joyn/blob/main/core-contracts/contracts/CoreCollection.sol#L51-L57

Add the following code to the top of initialize and remove from onlyValidSupply the function.

require( _maxSupply > 0, "CoreCollection: Max supply should be greater than 0"
);

Avg deployment from 3070877 to 3070313 with this change according to hardhat-gas-reporter

3 use != 0 instead of > 0 in if sentence. The following line use > 0 in if sentence of mintToken. != is cheaper than > 0.

https://github.com/code-423n4/2022-03-joyn/blob/main/core-contracts/contracts/CoreCollection.sol#L161

if (mintFee != 0) {}

4 Use cache for royaltyVaultInitialized() in _handlePayment. royaltyVaultInitialized()is used twice in _handlePayment, so it will be cheaper to use cache royaltyVaultInitialized().

https://github.com/code-423n4/2022-03-joyn/blob/main/core-contracts/contracts/ERC721Payable.sol#L51-L55

function _handlePayment(uint256 _amount) internal { bool vaultInitialized = royaltyVaultInitialized(); address recipient = vaultInitialized ? royaltyVault : address(this); payableToken.transferFrom(msg.sender, recipient, _amount); emit NewPayment(msg.sender, recipient, _amount, vaultInitialized); }

mintToken Avg from 228191 to 228124 with this change according to hardhat-gas-reporter

5 delete == true. In require you don’t use == true to check return value of IERC20().transfer and can save a little bit gas cost.

https://github.com/code-423n4/2022-03-joyn/blob/main/royalty-vault/contracts/RoyaltyVault.sol#L44 https://github.com/code-423n4/2022-03-joyn/blob/main/royalty-vault/contracts/RoyaltyVault.sol#L48 https://github.com/code-423n4/2022-03-joyn/blob/main/royalty-vault/contracts/RoyaltyVault.sol#L52-L55

require(IERC20().transfer, “Failed to transfer royalty Asset to”);

6 input validation must be checked earlier in the following function. royaltyAmount as input for incrementWindow must be checked at the top of the function to save gas cost in case of reverting with this validation.

https://github.com/code-423n4/2022-03-joyn/blob/main/splits/contracts/Splitter.sol#L164 Add this require sentence to the beginning of the function.

7 code duplication. splitAsset and royaltyAsset are always the same, so you can use a common variable for these variables. For example, you create new a variable transactionAsset instead of these variables. When you call createSplit, createSplitProxy will be called first and after that createVaultProxy will be called, so you can delete transactionAsset in createVaultProxy . You need to change the constructor of SplitProxy and ProxyVault too.

https://github.com/code-423n4/2022-03-joyn/blob/main/splits/contracts/SplitFactory.sol#L20-L21 https://github.com/code-423n4/2022-03-joyn/blob/main/splits/contracts/SplitFactory.sol#L86-L87 https://github.com/code-423n4/2022-03-joyn/blob/main/splits/contracts/SplitFactory.sol#L108-L109 https://github.com/code-423n4/2022-03-joyn/blob/main/splits/contracts/SplitFactory.sol#L162 https://github.com/code-423n4/2022-03-joyn/blob/main/splits/contracts/SplitFactory.sol#L172 https://github.com/code-423n4/2022-03-joyn/blob/main/royalty-vault/contracts/ProxyVault.sol#L19 https://github.com/code-423n4/2022-03-joyn/blob/main/splits/contracts/SplitProxy.sol#L20

address public transactionAsset;

8 set royaltyVault immutable. There is no setter for royaltyVault in ProxyVault, so royaltyVault in ProxyVault can be immutable.

https://github.com/code-423n4/2022-03-joyn/blob/main/royalty-vault/contracts/ProxyVault.sol#L9

address internal immutable royaltyVault;

9 use unchecked and prefix in for loop in the following loop.

https://github.com/code-423n4/2022-03-joyn/blob/main/core-contracts/contracts/CoreCollection.sol#L279 https://github.com/code-423n4/2022-03-joyn/blob/main/core-contracts/contracts/CoreFactory.sol https://github.com/code-423n4/2022-03-joyn/blob/main/splits/contracts/Splitter.sol#L50 https://github.com/code-423n4/2022-03-joyn/blob/main/splits/contracts/Splitter.sol#L274

for (uint256 i; i < length;) { unchecked { ++i; } }

10 use calldata instead of memory in createProject. The following inputs are memory. You can use calldata instated of memory to save gas.

https://github.com/code-423n4/2022-03-joyn/blob/main/core-contracts/contracts/CoreFactory.sol#L71-L72

string memory _projectId, Collection[] memory _collections

createProject() Avg from 602069 to 601329 only with this change according to hardhat-gas-reporter

11 use calldata instead of memory in addCollection. The following inputs are memory. You can use calldata instated of memory to save gas.

https://github.com/code-423n4/2022-03-joyn/blob/main/core-contracts/contracts/CoreFactory.sol#L109-L110

string calldata _projectId, Collection calldata _collection

addCollection() Avg from 442267 to 442141 only with this change according to hardhat-gas-reporter

12 use calldata instead of memory in getProject.

https://github.com/code-423n4/2022-03-joyn/blob/main/core-contracts/contracts/CoreFactory.sol#L128