Platform: Code4rena
Start Date: 23/06/2023
Pot Size: $60,500 USDC
Total HM: 31
Participants: 132
Period: 10 days
Judge: 0xean
Total Solo HM: 10
Id: 254
League: ETH
Rank: 103/132
Findings: 2
Award: $22.40
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: 0xnev
Also found by: 0xRobocop, 0xbrett8571, 0xkazim, 0xnacho, 3agle, 8olidity, ABAIKUNANBAEV, Bauchibred, Co0nan, CrypticShepherd, D_Auditor, DelerRH, HE1M, Iurii3, Kaysoft, MrPotatoMagic, RedOneN, RedTiger, Rolezn, SanketKogekar, Sathish9098, Timenov, Toshii, Vagner, bart1e, bytes032, codetilda, devival, halden, hals, kutugu, m_Rassska, naman1778, nonseodion, seth_lawson, solsaver, squeaky_cactus, totomanov, y51r, yudan, zaevlad
9.931 USDC - $9.93
The package.json configuration file says that the project is using 4.9.1 of OpenZeppelin which has a vulnerability.
Although there is no security vulnerability covering the project, it is recommended to use the latest version 4.9.2.
There is 1 instance of this issue in 1 file:
File: package.json 13:"@openzeppelin/contracts": "^4.9.1",
https://github.com/code-423n4/2023-06-lybra/blob/main/package.json
Consider using a modifier to implement access control instead of inlining the condition/requirement in the function’s body.
There are 9 instances of this issue in 7 files:
File: contracts/lybra/token/esLBR.sol 31: require(configurator.tokenMiner(msg.sender), "not authorized"); 39: require(configurator.tokenMiner(msg.sender), "not authorized");
https://github.com/code-423n4/2023-06-lybra/blob/main/contracts/lybra/token/esLBR.sol
File: contracts/lybra/pools/LybraRETHVault.sol 42: require(configurator.hasRole(keccak256("TIMELOCK"), msg.sender));
https://github.com/code-423n4/2023-06-lybra/blob/main/contracts/lybra/pools/LybraRETHVault.sol
File: contracts/lybra/token/LBR.sol 25: function mint(address user, uint256 amount) external returns (bool) { 26: require(configurator.tokenMiner(msg.sender), "not authorized"); 27: require(totalSupply() + amount <= maxSupply, "exceeding the maximum supply quantity."); 28: _mint(user, amount); 29: return true; 30: } 32: function burn(address user, uint256 amount) external returns (bool) { 33: require(configurator.tokenMiner(msg.sender), "not authorized"); 34: _burn(user, amount); 35: return true; 36: }
https://github.com/code-423n4/2023-06-lybra/blob/main/contracts/lybra/token/LBR.sol
File: contracts/lybra/pools/LybraStETHVault.sol 💰 📤 🧮 ♻️ 25: function setLidoRebaseTime(uint256 _time) external { 26: require(configurator.hasRole(keccak256("ADMIN"), msg.sender), "not authorized"); 27: lidoRebaseTime = _time; 28: }
https://github.com/code-423n4/2023-06-lybra/blob/main/contracts/lybra/pools/LybraStETHVault.sol
File: contracts/lybra/governance/LybraGovernance.sol 🧮 14: function _execute(uint256 /* proposalId */, address[] memory targets, uint256[] memory values, bytes[] memory calldatas, bytes32 descriptionHash) internal virtual override { 15: require(GovernanceTimelock.checkOnlyRole(keccak256("TIMELOCK"), msg.sender), "not authorized"); 16: super._execute(1, targets, values, calldatas, descriptionHash); 17: // _timelock.executeBatch{value: msg.value}(targets, values, calldatas, 0, descriptionHash); 18: }
https://github.com/code-423n4/2023-06-lybra/blob/main/contracts/lybra/governance/LybraGovernance.sol
File: contracts/lybra/token/PeUSDMainnetStableVision.sol 💰 79: function convertToPeUSD(address user, uint256 eusdAmount) public { 80: require(_msgSender() == user || _msgSender() == address(this), "MDM"); 81: require(EUSD.balanceOf(address(this)) + eusdAmount <= configurator.getEUSDMaxLocked(),"ESL"); 82: bool success = EUSD.transferFrom(user, address(this), eusdAmount); 83: require(success, "TF"); 84: uint256 share = EUSD.getSharesByMintedEUSD(eusdAmount); 85: userConvertInfo[user].depositedEUSDShares += share; 86: userConvertInfo[user].mintedPeUSD += eusdAmount; 87: _mint(user, eusdAmount); 88: }
File: contracts/lybra/miner/ProtocolRewardsPool.sol 📤 227: function notifyRewardAmount(uint amount, uint tokenType) external { 228: require(msg.sender == address(configurator)); 229: if (totalStaked() == 0) return; 230: require(amount > 0, "amount = 0"); 231: if(tokenType == 0) { 232: uint256 share = IEUSD(configurator.getEUSDAddress()).getSharesByMintedEUSD(amount); 233: rewardPerTokenStored = rewardPerTokenStored + (share * 1e18) / totalStaked(); 234: } else if(tokenType == 1) { 235: ERC20 token = ERC20(configurator.stableToken()); 236: rewardPerTokenStored = rewardPerTokenStored + (amount * 1e36 / token.decimals()) / totalStaked(); 237: } else { 238: rewardPerTokenStored = rewardPerTokenStored + (amount * 1e18) / totalStaked(); 239: } 240: }
https://github.com/code-423n4/2023-06-lybra/blob/main/contracts/lybra/miner/ProtocolRewardsPool.sol
While the compiler knows to optimize away the exponentiation, it’s still better coding practice to use idioms that do not require compiler optimization, if they exist
There are 3 instances of this issue in 3 files:
File: contracts/lybra/token/PeUSD.sol 14: ld2sdRatio = 10 ** (decimals - _sharedDecimals);
https://github.com/code-423n4/2023-06-lybra/blob/main/contracts/lybra/token/PeUSD.sol
File: contracts/lybra/token/LBR.sol 22: ld2sdRatio = 10 ** (decimals - _sharedDecimals);
https://github.com/code-423n4/2023-06-lybra/blob/main/contracts/lybra/token/LBR.sol
File: contracts/lybra/token/PeUSDMainnetStableVision.sol 60: ld2sdRatio = 10 ** (decimals - _sharedDecimals);
There is 1 instance of this issue in 1 file:
File: contracts/lybra/token/EUSD.sol 56: mapping(address => mapping(address => uint256)) private allowances;
https://github.com/code-423n4/2023-06-lybra/blob/main/contracts/lybra/token/EUSD.sol
Instead of the below mentioned file, all other files use 0.8.17 version of solidity.
There is 1 instance of this issue in 1 file:
File: contracts/lybra/miner/stakerewardV2pool.sol 2: pragma solidity ^0.8;
https://github.com/code-423n4/2023-06-lybra/blob/main/contracts/lybra/miner/stakerewardV2pool.sol
Empty or unused function parameters should be commented out as a better and declarative way to silence runtime warning messages. As an example, the following function may have these parameters refactored to:
There are 9 instances of this issue in 4 files:
File: contracts/lybra/token/PeUSD.sol 31: function _debitFrom(address _from, uint16, bytes32, uint _amount) internal virtual override returns (uint) { 38: function _creditTo(uint16, address _toAddress, uint _amount) internal virtual override returns (uint) {
https://github.com/code-423n4/2023-06-lybra/blob/main/contracts/lybra/token/PeUSD.sol
File: contracts/lybra/token/LBR.sol 49: function _debitFrom(address _from, uint16, bytes32, uint _amount) internal virtual override returns (uint) { 56: function _creditTo(uint16, address _toAddress, uint _amount) internal virtual override returns (uint) {
https://github.com/code-423n4/2023-06-lybra/blob/main/contracts/lybra/token/LBR.sol
File: contracts/lybra/governance/LybraGovernance.sol 🧮 76: function _countVote(uint256 proposalId, address account, uint8 support, uint256 weight, bytes memory) internal override { 98: function _getVotes(address account, uint256 timepoint, bytes memory) internal view override returns (uint256){ 106: function _execute(uint256 /* proposalId */, address[] memory targets, uint256[] memory values, bytes[] memory calldatas, bytes32 descriptionHash) internal virtual override {
https://github.com/code-423n4/2023-06-lybra/blob/main/contracts/lybra/governance/LybraGovernance.sol
File: contracts/lybra/token/PeUSDMainnetStableVision.sol 💰 184: function _debitFrom(address _from, uint16, bytes32, uint _amount) internal virtual override returns (uint) { 191: function _creditTo(uint16, address _toAddress, uint _amount) internal virtual override returns (uint) {
#0 - c4-sponsor
2023-07-27T06:18:48Z
LybraFinance marked the issue as sponsor confirmed
#1 - c4-judge
2023-07-28T00:04:47Z
0xean marked the issue as grade-b
🌟 Selected for report: JCN
Also found by: 0xAnah, DavidGiladi, MohammedRizwan, Rageur, Raihan, ReyAdmirado, Rolezn, SAAJ, SAQ, SM3_SS, Sathish9098, ayo_dev, dharma09, fatherOfBlocks, hunter_w3b, mgf15, mrudenko, naman1778, shamsulhaq123, souilos, turvy_fuzz
12.4743 USDC - $12.47
Checking zero address can be improved by replacing the require statement with Assembly.Solidity has a lot of guardrails that can be removed (with care) for optimization purposes, especially for simple functionality like checking if an address is zero.
There are 18 instances of this issue in 7 files:
File: contracts/lybra/miner/stakerewardV2pool.sol 60: if (_account != address(0)) {
https://github.com/code-423n4/2023-06-lybra/blob/main/contracts/lybra/miner/stakerewardV2pool.sol
File: contracts/lybra/token/PeUSDMainnetStableVision.sol 64: require(to != address(0), "TZA");
File: contracts/lybra/token/EUSD.sol 367: require(_owner != address(0), "APPROVE_FROM_ZERO_ADDRESS"); 368: require(_spender != address(0), "APPROVE_TO_ZERO_ADDRESS"); 392: require(_sender != address(0), "TRANSFER_FROM_THE_ZERO_ADDRESS"); 393: require(_recipient != address(0), "TRANSFER_TO_THE_ZERO_ADDRESS"); 412: require(_recipient != address(0), "MINT_TO_THE_ZERO_ADDRESS"); 441: require(_account != address(0), "BURN_FROM_THE_ZERO_ADDRESS"); 460: require(_account != address(0), "BURN_FROM_THE_ZERO_ADDRESS");
https://github.com/code-423n4/2023-06-lybra/blob/main/contracts/lybra/token/EUSD.sol
File: contracts/lybra/configuration/LybraConfigurator.sol 99: if (address(EUSD) == address(0)) EUSD = IEUSD(_eusd); 100: if (address(peUSD) == address(0)) peUSD = IEUSD(_peusd);
File: contracts/lybra/miner/EUSDMiningIncentives.sol 76: if (_account != address(0)) {
https://github.com/code-423n4/2023-06-lybra/blob/main/contracts/lybra/miner/EUSDMiningIncentives.sol
File: contracts/lybra/pools/base/LybraEUSDVaultBase.sol 99: require(onBehalfOf != address(0), "TZA"); 127: require(onBehalfOf != address(0), "MINT_TO_THE_ZERO_ADDRESS"); 141: require(onBehalfOf != address(0), "BURN_TO_THE_ZERO_ADDRESS");
File: contracts/lybra/pools/base/LybraPeUSDVaultBase.sol 83: require(onBehalfOf != address(0), "TZA"); 97: require(onBehalfOf != address(0), "TZA"); 111: require(onBehalfOf != address(0), "TZA");
contract GasTest is DSTest { Contract0 c0; Contract1 c1; function setUp() public { c0 = new Contract0(); c1 = new Contract1(); } function testGas() public { c0.solidity_notZero(0xFD2dabe9DFcc4d88a12A9D0D40D834E81217Cccf); c1.assembly_notZero(0xFD2dabe9DFcc4d88a12A9D0D40D834E81217Cccf); } } contract Contract0 { error ZeroAddress(); function solidity_notZero(address toCheck) public pure returns(bool success) { if(toCheck == address(0)) revert ZeroAddress(); return true; } } contract Contract1{ error ZeroAddress(); function assembly_notZero(address toCheck) public pure returns(bool success) { assembly { if iszero(toCheck) { let ptr := mload(0x40) mstore(ptr, 0xd92e233d00000000000000000000000000000000000000000000000000000000) // selector for `ZeroAddress()` revert(ptr, 0x4) } } return true; } }
src/test/GasTest.t.sol:Contract0 contract | |||||
---|---|---|---|---|---|
Deployment Cost | Deployment Size | ||||
55905 | 311 | ||||
Function Name | min | avg | median | max | # calls |
solidity_notZero | 323 | 323 | 323 | 323 | 1 |
src/test/GasTest.t.sol:Contract1 contract | |||||
---|---|---|---|---|---|
Deployment Cost | Deployment Size | ||||
50099 | 281 | ||||
Function Name | min | avg | median | max | # calls |
assembly_notZero | 317 | 317 | 317 | 317 | 1 |
When writing value for variables whose type is address, make use of assembly code instead of solidity code.
There are 6 instances of this issue in 2 files:
File: contracts/lybra/configuration/LybraConfigurator.sol 262: stableToken = _token;
File: contracts/lybra/miner/EUSDMiningIncentives.sol 85: LBR = _lbr; 86: esLBR = _eslbr; 97: pools = _pools; 125: ethlbrStakePool = _pool; 126: ethlbrLpToken = _lp;
https://github.com/code-423n4/2023-06-lybra/blob/main/contracts/lybra/miner/EUSDMiningIncentives.sol
contract GasTest is DSTest { Contract0 c0; Contract1 c1; function setUp() public { c0 = new Contract0(); c1 = new Contract1(); } function testGas() public { c0.setOwnerAssembly(0xFD2dabe9DFcc4d88a12A9D0D40D834E81217Cccf); c1.setOwner(0xFD2dabe9DFcc4d88a12A9D0D40D834E81217Cccf); } } contract Contract0 { address owner; function setOwnerAssembly(address _owner) public { assembly{ sstore(owner.slot,_owner) } } } contract Contract1 { address owner; function setOwner(address _owner) public { owner = _owner; } }
Contract0 contract | |||||
---|---|---|---|---|---|
Deployment Cost | Deployment Size | ||||
35287 | 207 | ||||
Function Name | min | avg | median | max | # calls |
setOwnerAssembly | 22324 | 22324 | 22324 | 22324 | 1 |
Contract1 contract | |||||
---|---|---|---|---|---|
Deployment Cost | Deployment Size | ||||
48499 | 273 | ||||
Function Name | min | avg | median | max | # calls |
setOwner | 22363 | 22363 | 22363 | 22363 | 1 |
Using nesting is cheaper than using && multiple check combinations. There are more advantages, such as easier to read code and better coverage reports.
There are 4 instances of this issue in 4 files:
File: contracts/lybra/token/PeUSD.sol 46: if (_from != address(this) && _from != spender)
https://github.com/code-423n4/2023-06-lybra/blob/main/contracts/lybra/token/PeUSD.sol
File: contracts/lybra/token/LBR.sol 64: if (_from != address(this) && _from != spender)
https://github.com/code-423n4/2023-06-lybra/blob/main/contracts/lybra/token/LBR.sol
File: contracts/lybra/token/PeUSDMainnetStableVision.sol 199: if (_from != address(this) && _from != spender)
File: contracts/lybra/pools/base/LybraEUSDVaultBase.sol 204: if (msg.sender != provider && onBehalfOfCollateralRatio >= 1e20 + configurator.vaultKeeperRatio(address(this)) * 1e18) {
contract GasTest is DSTest { Contract0 c0; Contract1 c1; function setUp() public { c0 = new Contract0(); c1 = new Contract1(); } function testGas() public { c0.checkAge(19); c1.checkAgeOptimized(19); } } contract Contract0 { function checkAge(uint8 _age) public returns(string memory){ if(_age>18 && _age<22){ return "Eligible"; } } } contract Contract1 { function checkAgeOptimized(uint8 _age) public returns(string memory){ if(_age>18){ if(_age<22){ return "Eligible"; } } } }
Contract0 contract | |||||
---|---|---|---|---|---|
Deployment Cost | Deployment Size | ||||
76923 | 416 | ||||
Function Name | min | avg | median | max | # calls |
checkAge | 651 | 651 | 651 | 651 | 1 |
Contract1 contract | |||||
---|---|---|---|---|---|
Deployment Cost | Deployment Size | ||||
76323 | 413 | ||||
Function Name | min | avg | median | max | # calls |
checkAgeOptimized | 645 | 645 | 645 | 645 | 1 |
On Remix, given only uint256 types, the following are logical equivalents, but don’t cost the same amount of gas:
(a != b || c != d || e != f) costs 571 ((a ^ b) | (c ^ d) | (e ^ f)) != 0 costs 498 (saving 73 gas) Consider rewriting as following to save gas:
To have a == b means that every 0 and 1 match on both variables. Meaning that a XOR (operator ^) would evaluate to 0 ((a ^ b) == 0), as it excludes by definition any equalities. Now, if a != b, this means that there’s at least somewhere a 1 and a 0 not matching between a and b, making (a ^ b) != 0.
Both formulas are logically equivalent and using the XOR bitwise operator costs actually the same amount of gas:
However, it is much cheaper to use the bitwise OR operator (|) than comparing the truthy or falsy values
There is 1 instance of this issue in 1 file:
File: contracts/lybra/token/PeUSDMainnetStableVision.sol 80: require(_msgSender() == user || _msgSender() == address(this), "MDM");
contract GasTest is DSTest { Contract0 c0; Contract1 c1; function setUp() public { c0 = new Contract0(); c1 = new Contract1(); } function testGas() public { c0.not_optimized(1,2); c1.optimized(1,2); } } contract Contract0 { function not_optimized(uint8 a,uint8 b) public returns(bool){ return ((a==1) || (b==1)); } } contract Contract1 { function optimized(uint8 a,uint8 b) public returns(bool){ return ((a ^ 1) & (b ^ 1)) == 0; } }
Contract0 contract | |||||
---|---|---|---|---|---|
Deployment Cost | Deployment Size | ||||
46099 | 261 | ||||
Function Name | min | avg | median | max | # calls |
not_optimized | 456 | 456 | 456 | 456 | 1 |
Contract1 contract | |||||
---|---|---|---|---|---|
Deployment Cost | Deployment Size | ||||
42493 | 243 | ||||
Function Name | min | avg | median | max | # calls |
optimized | 430 | 430 | 430 | 430 | 1 |
Counting down is more gas efficient than counting up because neither we are making zero variable to non-zero variable and also we will get gas refund in the last transaction when making non-zero to zero variable.
There are 3 instances of this issue in 3 files:
File: contracts/lybra/configuration/LybraConfigurator.sol 236: for (uint256 i = 0; i < _contracts.length; i++) {
File: contracts/lybra/miner/EUSDMiningIncentives.sol 94: for (uint i = 0; i < _pools.length; i++) { 138: for (uint i = 0; i < pools.length; i++) {
https://github.com/code-423n4/2023-06-lybra/blob/main/contracts/lybra/miner/EUSDMiningIncentives.sol
contract GasTest is DSTest { Contract0 c0; Contract1 c1; function setUp() public { c0 = new Contract0(); c1 = new Contract1(); } function testGas() public { c0.AddNum(); c1.AddNum(); } } contract Contract0 { uint256 num = 3; function AddNum() public { uint256 _num = num; for(uint i=0;i<=9;i++){ _num = _num +1; } num = _num; } } contract Contract1 { uint256 num = 3; function AddNum() public { uint256 _num = num; for(uint i=9;i>=0;i--){ _num = _num +1; } num = _num; } }
Contract0 contract | |||||
---|---|---|---|---|---|
Deployment Cost | Deployment Size | ||||
77011 | 311 | ||||
Function Name | min | avg | median | max | # calls |
AddNum | 7040 | 7040 | 7040 | 7040 | 1 |
Contract1 contract | |||||
---|---|---|---|---|---|
Deployment Cost | Deployment Size | ||||
73811 | 295 | ||||
Function Name | min | avg | median | max | # calls |
AddNum | 3819 | 3819 | 3819 | 3819 | 1 |
When a function with a memory array is called externally, the abi.decode() step has to use a for-loop to copy each index of the calldata to the memory index. Each iteration of this for-loop costs at least 60 gas (i.e. 60 * <mem_array>.length). Using calldata directly, obliviates the need for such a loop in the contract code and runtime execution. Note that even if an interface defines a function as having memory arguments, it’s still valid for implementation contracs to use calldata arguments instead.
If the array is passed to an internal function which passes the array to another internal function where the array is modified and therefore memory is used in the external call, it’s still more gass-efficient to use calldata when the external function uses modifiers, since the modifiers may prevent the internal functions from being called. Structs have the same overhead as an array of length one
Note that I’ve also flagged instances where the function is public but can be marked as external since it’s not called by the contract, and cases where a constructor is involved
There are 2 instances of this issue in 2 files:
File: contracts/lybra/miner/esLBRBoost.sol 33: function addLockSetting(esLBRLockSetting memory setting) external onlyOwner {
https://github.com/code-423n4/2023-06-lybra/blob/main/contracts/lybra/miner/esLBRBoost.sol
File: contracts/lybra/miner/EUSDMiningIncentives.sol 93: function setPools(address[] memory _pools) external onlyOwner {
https://github.com/code-423n4/2023-06-lybra/blob/main/contracts/lybra/miner/EUSDMiningIncentives.sol
contract GasTest is DSTest { Contract0 c0; Contract1 c1; function setUp() public { c0 = new Contract0(); c1 = new Contract1(); } function testGas() public { c0.not_optimized("Naman"); c1.optimized("Naman"); } } contract Contract0 { function not_optimized(string memory a) public returns(string memory){ return a; } } contract Contract1 { function optimized(string calldata a) public returns(string calldata){ return a; } }
Contract0 contract | |||||
---|---|---|---|---|---|
Deployment Cost | Deployment Size | ||||
100747 | 535 | ||||
Function Name | min | avg | median | max | # calls |
not_optimized | 790 | 790 | 790 | 790 | 1 |
Contract1 contract | |||||
---|---|---|---|---|---|
Deployment Cost | Deployment Size | ||||
66917 | 366 | ||||
Function Name | min | avg | median | max | # calls |
optimized | 556 | 556 | 556 | 556 | 1 |
If the variable is only accessed once, it’s cheaper to use the state variable directly that one time, and save the 3 gas the extra stack assignment would spend.
There are 4 instances of this issue in 4 files:
File: contracts/lybra/miner/stakerewardV2pool.sol 136: uint256 remainingRewards = (finishAt - block.timestamp) * rewardRatio;
https://github.com/code-423n4/2023-06-lybra/blob/main/contracts/lybra/miner/stakerewardV2pool.sol
File: contracts/lybra/miner/EUSDMiningIncentives.sol 233: uint256 remainingRewards = (finishAt - block.timestamp) * rewardRatio;
https://github.com/code-423n4/2023-06-lybra/blob/main/contracts/lybra/miner/EUSDMiningIncentives.sol
File: contracts/lybra/pools/base/LybraEUSDVaultBase.sol 236: uint256 providerCollateralRatio = (depositedAsset[provider] * assetPrice * 100) / borrowed[provider];
File: contracts/lybra/pools/base/LybraVaultBase.sol 161: uint256 providerCollateralRatio = (depositedAsset[provider] * assetPrice * 100) / borrowed[provider];
contract GasTest is DSTest { Contract0 c0; Contract1 c1; function setUp() public { c0 = new Contract0(); c1 = new Contract1(); } function testGas() public { c0.not_optimized(); c1.optimized(); } } contract Contract0 { uint256 num = 5; uint256 sum; function not_optimized() public returns(bool){ uint256 num1 = num; sum = num1 + 2; } } contract Contract1 { uint256 num = 5; uint256 sum; function optimized() public returns(bool){ sum = num + 2; } }
Contract0 contract | |||||
---|---|---|---|---|---|
Deployment Cost | Deployment Size | ||||
63799 | 244 | ||||
Function Name | min | avg | median | max | # calls |
not_optimized | 24462 | 24462 | 24462 | 24462 | 1 |
Contract1 contract | |||||
---|---|---|---|---|---|
Deployment Cost | Deployment Size | ||||
63599 | 243 | ||||
Function Name | min | avg | median | max | # calls |
optimized | 24460 | 24460 | 24460 | 24460 | 1 |
<x> * 2 is the same as <x> << 1. While the compiler uses the SHR opcode to accomplish both, the version that uses division incurs an overhead of 20 gas due to JUMPs to and from a compiler utility function that introduces checks which can be avoided by using unchecked {} around the division by two.
There are 2 instances of this issue in 2 files:
File: contracts/lybra/pools/base/LybraEUSDVaultBase.sol 159: require(assetAmount * 2 <= depositedAsset[onBehalfOf], "a max of 50% collateral can be liquidated");
File: contracts/lybra/pools/base/LybraPeUSDVaultBase.sol 130: require(assetAmount * 2 <= depositedAsset[onBehalfOf], "a max of 50% collateral can be liquidated");
contract GasTest is DSTest { Contract0 c0; Contract1 c1; function setUp() public { c0 = new Contract0(); c1 = new Contract1(); } function testGas() public { c0.not_optimized(); c1.optimized(); } } contract Contract0 { uint256 num = 5; uint256 mul; function not_optimized() public returns(bool){ mul = num * 2; } } contract Contract1 { uint256 num = 5; uint256 mul; function optimized() public returns(bool){ mul = num << 2; } }
Contract0 contract | |||||
---|---|---|---|---|---|
Deployment Cost | Deployment Size | ||||
64399 | 247 | ||||
Function Name | min | avg | median | max | # calls |
not_optimized | 24476 | 24476 | 24476 | 24476 | 1 |
Contract1 contract | |||||
---|---|---|---|---|---|
Deployment Cost | Deployment Size | ||||
47581 | 161 | ||||
Function Name | min | avg | median | max | # calls |
optimized | 24361 | 24361 | 24361 | 24361 | 1 |
#0 - c4-sponsor
2023-07-27T06:21:50Z
LybraFinance marked the issue as sponsor acknowledged
#1 - c4-judge
2023-07-27T23:41:42Z
0xean marked the issue as grade-b