code-423n4 / 2022-02-jpyc-findings

1 stars 0 forks source link

Gas Optimizations #17

Open code423n4 opened 2 years ago

code423n4 commented 2 years ago

2022-02-jpyc gas optimization

1 use initial value for uint256 variable.

https://github.com/code-423n4/2022-02-jpyc/blob/main/contracts/v1/FiatTokenV1.sol#L58

uint256 internal totalSupply_;

2 use function param to emit an event instead of storage to save gas. https://github.com/code-423n4/2022-02-jpyc/blob/main/contracts/v1/FiatTokenV1.sol#L383

masterMinter is storage, so it costs extra gas. In this case, you can use _newMasterMinter instead of masterMinter.

emit MasterMinterChanged(_newMasterMinter);

3 Use unchecked for calculations in which over/underflow is checked.

https://github.com/code-423n4/2022-02-jpyc/blob/main/contracts/v1/FiatTokenV1.sol#L146 https://github.com/code-423n4/2022-02-jpyc/blob/main/contracts/v1/FiatTokenV1.sol#L276 https://github.com/code-423n4/2022-02-jpyc/blob/main/contracts/v1/FiatTokenV1.sol#L316 https://github.com/code-423n4/2022-02-jpyc/blob/main/contracts/v1/FiatTokenV1.sol#L372 https://github.com/code-423n4/2022-02-jpyc/blob/main/contracts/v1/FiatTokenV1.sol#L449

Wrap with

unchecked {

}

4 Using the cache is gas efficient.

You can use the cache for allowed[owner][spender] in _decreaseAllowance. Also allowed[from][msg.sender] in transferForm too.

https://github.com/code-423n4/2022-02-jpyc/blob/main/contracts/v1/FiatTokenV1.sol#L440-L450 https://github.com/code-423n4/2022-02-jpyc/blob/main/contracts/v1/FiatTokenV1.sol#L272-L276 https://github.com/code-423n4/2022-02-jpyc/blob/main/contracts/v2/FiatTokenV2.sol#L457-L460 https://github.com/code-423n4/2022-02-jpyc/blob/main/contracts/v2/FiatTokenV2.sol#L281-L285

function _decreaseAllowance( address owner, address spender, uint256 decrement ) internal override { uint _allowed = allowance(owner, spender); require(decrement <= _allowed, “ERC20: decreased allowance below zero”); unchecked { _approve(owner, spender, allowed - dcrement); } }

You need to change the visibility of allowance to public if you call allowance() in _decreaseAllowance().

5 Use cache for balances[from]in _transfer.

https://github.com/code-423n4/2022-02-jpyc/blob/main/contracts/v2/FiatTokenV2.sol#L322-L326 https://github.com/code-423n4/2022-02-jpyc/blob/main/contracts/v1/FiatTokenV1.sol#L312-L317

uint256 balanceFrom = balances[from]; require(value <= balanceFrom, “ERC20: transfer amount exceeds balance”); balances[from] = balanceFrom - value;

6 delete the unnecessary variable.

In my opinion, you can delete minters because onlyMinters which uses minters can also use minterAllowed to execute his task and onlyMinters for burn function must not be checked(because burn has not directly to do with minter)

https://github.com/code-423n4/2022-02-jpyc/blob/main/contracts/v1/FiatTokenV1.sol#L59 https://github.com/code-423n4/2022-02-jpyc/blob/main/contracts/v2/FiatTokenV2.sol#L59

and you can also delete the following function

https://github.com/code-423n4/2022-02-jpyc/blob/main/contracts/v2/FiatTokenV2.sol#L182-L184

Modifier onlyMinters() { require(minterAllowed[msg.sender] != 0, “FiatToken: Mint is not available”); _; }

7 use custom errors instead of require to save gas.

https://github.com/code-423n4/2022-02-jpyc/blob/main/contracts/v1/FiatTokenV1.sol#L78-L94 https://github.com/code-423n4/2022-02-jpyc/blob/main/contracts/v1/FiatTokenV1.sol#L135-L136 https://github.com/code-423n4/2022-02-jpyc/blob/main/contracts/v1/FiatTokenV1.sol#L139-L142 https://github.com/code-423n4/2022-02-jpyc/blob/main/contracts/v1/FiatTokenV1.sol#L156-L159 https://github.com/code-423n4/2022-02-jpyc/blob/main/contracts/v1/FiatTokenV1.sol#L245-L246 https://github.com/code-423n4/2022-02-jpyc/blob/main/contracts/v1/FiatTokenV1.sol#L271-L274 https://github.com/code-423n4/2022-02-jpyc/blob/main/contracts/v1/FiatTokenV1.sol#L309-L314 https://github.com/code-423n4/2022-02-jpyc/blob/main/contracts/v1/FiatTokenV1.sol#L368-L369 https://github.com/code-423n4/2022-02-jpyc/blob/main/contracts/v1/FiatTokenV1.sol#L378-L381 https://github.com/code-423n4/2022-02-jpyc/blob/main/contracts/v1/FiatTokenV1.sol#L445-L448 https://.com/code-423n4/2022-02-jpyc/blob/main/contracts/v2/FiatTokenV2.sol#L122 https://github.com/code-423n4/2022-02-jpyc/blob/main/contracts/v2/FiatTokenV2.sol#L142-L149 https://github.com/code-423n4/2022-02-jpyc/blob/main/contracts/v2/FiatTokenV2.sol#L163-L166 https://github.com/code-423n4/2022-02-jpyc/blob/main/contracts/v2/FiatTokenV2.sol#L253-L254 https://github.com/code-423n4/2022-02-jpyc/blob/main/contracts/v2/FiatTokenV2.sol#L280-L283 https://github.com/code-423n4/2022-02-jpyc/blob/main/contracts/v2/FiatTokenV2.sol#L319-L324 https://github.com/code-423n4/2022-02-jpyc/blob/main/contracts/v2/FiatTokenV2.sol#L378-L379 https://github.com/code-423n4/2022-02-jpyc/blob/main/contracts/v2/FiatTokenV2.sol#L388-L391 https://github.com/code-423n4/2022-02-jpyc/blob/main/contracts/v2/FiatTokenV2.sol#L456-L459 https://github.com/code-423n4/2022-02-jpyc/blob/main/contracts/v2/FiatTokenV2.sol#L611-L614 https://github.com/code-423n4/2022-02-jpyc/blob/main/contracts/v2/FiatTokenV2.sol#L625-L628 https://github.com/code-423n4/2022-02-jpyc/blob/main/contracts/v2/FiatTokenV2.sol#L660-L663

thurendous commented 2 years ago

No. 1 and 2 is valid. But there are a lot of duplicates about this. e.g. #27

thurendous commented 2 years ago

No. 3 and 4 can be valid too. Although there are duplicates. #27

thurendous commented 2 years ago

5 Use cache for balances[from]in _transfer.

Fixed and thanks!

Final change can be viewed here.