Platform: Code4rena
Start Date: 04/03/2024
Pot Size: $36,500 USDC
Total HM: 9
Participants: 80
Period: 7 days
Judge: hansfriese
Total Solo HM: 2
Id: 332
League: ETH
Rank: 45/80
Findings: 1
Award: $19.37
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: slvDev
Also found by: 0x11singh99, 0xhacksmithh, SAQ, SY_S, albahaca, dharma09, hunter_w3b, shamsulhaq123, unique
19.3678 USDC - $19.37
Instead of using abi.decode, we can use assembly to decode our desired calldata values directly. This will allow us to avoid decoding calldata values that we will not use.
reference : <ins>https://code4rena.com/reports/2023-08-goodentry#g-02-use-assembly-in-place-of-abidecode-to-extract-calldata-values-more-efficiently</ins>
777: uint256 returnedDecimals = abi.decode(encodedDecimals, (uint256));
Â
function _mint(address _receiver, uint256 _amount) internal virtual override { twabController.mint(_receiver, SafeCast.toUint96(_amount)); emit Transfer(address(0), _receiver, _amount); }
Â
function _burn(address _owner, uint256 _amount) internal virtual override { twabController.burn(_owner, SafeCast.toUint96(_amount)); emit Transfer(_owner, address(0), _amount); }
External calls are expensive as they use the STATICCALL
/CALL
opcode (~100 gas). If you are calling the same external function more than once you should cache the return value to avoid an unnecessary STATICCALL
/CALL
.
it's generally more gas-efficient to use constants instead of type(uintX).max when you need to set the maximum value of an unsigned integer type.
The reason for this is that the type(uintX).max expression involves a computation at runtime, whereas a constant is evaluated at compile-time. This means that using type(uintX).max can result in additional gas costs for each transaction that involves the expression.
By using a constant instead of type(uintX).max, you can avoid these additional gas costs and make your code more efficient.
Here's an example of how you can use a constant instead of type(uintX).max:
contract MyContract { uint120 constant MAX_VALUE = 2**120 - 1; function doSomething(uint120 value) public { require(value <= MAX_VALUE, "Value exceeds maximum"); // Do something } }
In the above example, we have a contract with a constant MAX_VALUE that represents the maximum value of a uint120. When the doSomething function is called with a value parameter, it checks whether the value is less than or equal to MAX_VALUE using the <= operator.
By using a constant instead of type(uint120).max, we can make our code more efficient and reduce the gas cost of our contract.
It's important to note that using constants can make your code more readable and maintainable, since the value is defined in one place and can be easily updated if necessary. However, constants should be used with caution and only when their value is known at compile-time.
778: if (returnedDecimals <= type(uint8).max) {
800: return type(uint96).max - _totalSupply;
The EVM only operates on 32 bytes/ 256 bits at a time. This means that if you use uint8, EVM has to first convert it uint256 to work on it and the conversion costs extra gas! You may wonder, What were the devs thinking? Why did they create smaller variables then? The answer lies in packing. In solidity, you can pack multiple small variables into one slot, but if you are defining a lone variable and can’t pack it, it’s optimal to use a uint256 rather than uint8.
Â
It is considered a best practice to verify for zero values before executing any transfers within smart contract functions. This approach helps prevent unnecessary external calls and can effectively reduce gas costs.
This practice is particularly crucial when dealing with the transfer of tokens or ether, as sending these assets to an address with a zero value will result in the loss of those assets.
In Solidity, you can determine whether a value is zero by utilizing the == operator. Here's an example demonstrating how to check for a zero value before performing a transfer:
//example function transfer(address payable recipient, uint256 amount) public { require(amount > 0, "Amount must be greater than zero"); recipient.transfer(amount); }
101: twabController.transfer(_from, _to, SafeCast.toUint96(_amount));
Â
If you can fit your data in 32 bytes, then you should use bytes32 datatype rather than bytes or strings as it is much cheaper in solidity. Basically, Any fixed size variable in solidity is cheaper than variable size.
event NewPrizeVault( PrizeVault indexed vault, IERC4626 indexed yieldVault, PrizePool indexed prizePool, string name, string symbol );
#0 - raymondfam
2024-03-13T04:08:45Z
7 generic G
#1 - c4-pre-sort
2024-03-13T04:08:50Z
raymondfam marked the issue as sufficient quality report
#2 - c4-judge
2024-03-18T02:56:30Z
hansfriese marked the issue as grade-b