Issue | Instances | |
---|---|---|
[GAS-1] | Cache array length outside of loop | 10 |
[GAS-2] | Use != 0 instead of > 0 for unsigned integer comparison | 77 |
[GAS-3] | Don't initialize variables with default value | 59 |
[GAS-4] | Use shift Right/Left instead of division/multiplication if possible | 10 |
[GAS-5] | Using bools for storage incurs overhead | 15 |
[GAS-6] | Use Custom Errors | 33 |
[GAS-7] | ++i costs less gas than i++ , especially when it's used in for -loops (--i /i-- too) |
29 |
[GAS-8] | Using private rather than public for constants, saves gas |
7 |
If not cached, the solidity compiler will always read the length of the array during each iteration. That is, if it is a storage array, this is an extra sload operation (100 additional extra gas for each iteration except for the first) and if it is a memory array, this is an extra mload operation (3 additional gas for each iteration except for the first).
Instances (10):
File: contracts/Core/SwapPair.sol
268: for (uint i = 0; i < _prices.length; i++) {
File: contracts/periphery/Bribe.sol
235: for (uint i = 0; i < tokens.length; i++) {
251: for (uint i = 0; i < tokens.length; i++) {
File: contracts/periphery/Gauge.sol
299: for (uint i = 0; i < tokens.length; i++) {
File: contracts/periphery/Voter.sol
309: for (uint i = 0; i < _gauges.length; i++) {
352: for (uint i = 0; i < _gauges.length; i++) {
363: for (uint i = 0; i < _bribes.length; i++) {
374: for (uint i = 0; i < _fees.length; i++) {
382: for (uint i = 0; i < _gauges.length; i++) {
415: for (uint x = 0; x < _gauges.length; x++) {
Instances (77):
File: contracts/Core/SwapPair.sol
143: if (claimed0 > 0 || claimed1 > 0) {
143: if (claimed0 > 0 || claimed1 > 0) {
161: if (_ratio > 0) {
175: if (_ratio > 0) {
185: if (_supplied > 0) {
194: if (_delta0 > 0) {
198: if (_delta1 > 0) {
218: if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {
314: require(liquidity > 0, 'ILM'); // SwapPair: INSUFFICIENT_LIQUIDITY_MINTED
333: require(amount0 > 0 && amount1 > 0, 'ILB'); // SwapPair: INSUFFICIENT_LIQUIDITY_BURNED
333: require(amount0 > 0 && amount1 > 0, 'ILB'); // SwapPair: INSUFFICIENT_LIQUIDITY_BURNED
347: require(amount0Out > 0 || amount1Out > 0, 'IOA'); // SwapPair: INSUFFICIENT_OUTPUT_AMOUNT
347: require(amount0Out > 0 || amount1Out > 0, 'IOA'); // SwapPair: INSUFFICIENT_OUTPUT_AMOUNT
356: if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens
357: if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens
358: if (data.length > 0) ISwapCallee(to).hook(msg.sender, amount0Out, amount1Out, data); // callback, used for flash loans
364: require(amount0In > 0 || amount1In > 0, 'IIA'); // SwapPair: INSUFFICIENT_INPUT_AMOUNT
364: require(amount0In > 0 || amount1In > 0, 'IIA'); // SwapPair: INSUFFICIENT_INPUT_AMOUNT
367: if (amount0In > 0) _update0(amount0In * fee / 1e6); // accrue fees for token0 and move them out of pool
368: if (amount1In > 0) _update1(amount1In * fee / 1e6); // accrue fees for token1 and move them out of pool
538: require(token.code.length > 0);
File: contracts/periphery/Bribe.sol
192: if (_nCheckPoints > 0 && checkpoints[tokenId][_nCheckPoints - 1].timestamp == _timestamp) {
203: if (_nCheckPoints > 0 && rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp == timestamp) {
215: if (_nCheckPoints > 0 && supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp) {
241: if (_reward > 0) _safeTransfer(tokens[i], msg.sender, _reward);
257: if (_reward > 0) _safeTransfer(tokens[i], _owner, _reward);
291: if (sp0.supply > 0) {
335: if (_endIndex > 0) {
338: if (sp0.supply > 0) {
350: if (sp.supply > 0) {
372: if (_endIndex > 0) {
424: require(amount > 0);
445: require(rewardRate[token] > 0);
454: require(token.code.length > 0);
461: require(token.code.length > 0);
File: contracts/periphery/Gauge.sol
116: if (claimed0 > 0 || claimed1 > 0) {
116: if (claimed0 > 0 || claimed1 > 0) {
120: if (_fees0 > IBribe(bribe).left(_token0) && _fees0 / DURATION > 0) {
127: if (_fees1 > IBribe(bribe).left(_token1) && _fees1 / DURATION > 0) {
246: if (_nCheckPoints > 0 && checkpoints[account][_nCheckPoints - 1].timestamp == _timestamp) {
257: if (_nCheckPoints > 0 && rewardPerTokenCheckpoints[token][_nCheckPoints - 1].timestamp == timestamp) {
269: if (_nCheckPoints > 0 && supplyCheckpoints[_nCheckPoints - 1].timestamp == _timestamp) {
305: if (_reward > 0) _safeTransfer(tokens[i], account, _reward);
353: if (sp0.supply > 0) {
399: if (_endIndex > 0) {
402: if (sp0.supply > 0) {
413: if (sp.supply > 0) {
436: if (_endIndex > 0) {
458: require(amount > 0);
465: if (tokenId > 0) {
508: if (tokenId > 0) {
537: require(amount > 0);
558: require(rewardRate[token] > 0);
567: require(token.code.length > 0);
574: require(token.code.length > 0);
581: require(token.code.length > 0);
File: contracts/periphery/Multiswap.sol
44: require(msg.value > 0, "no ETH sent");
54: require(_amount > 0, "no tokens sent");
File: contracts/periphery/Voter.sol
157: if (_votes > 0) {
216: if (_usedWeight > 0) IVotingEscrow(_ve).voting(_tokenId);
273: if (tokenId > 0) IVotingEscrow(_ve).attach(tokenId);
284: if (tokenId > 0) IVotingEscrow(_ve).detach(tokenId);
302: if (_ratio > 0) {
332: if (_supplied > 0) {
337: if (_delta > 0) {
393: if (_claimable > IGauge(_gauge).left(base) && _claimable / DURATION > 0) {
434: require(token.code.length > 0);
File: contracts/periphery/VotingEscrow.sol
352: return size > 0;
484: if (old_locked.end > block.timestamp && old_locked.amount > 0) {
488: if (new_locked.end > block.timestamp && new_locked.amount > 0) {
507: if (_epoch > 0) {
707: require(_value > 0); // dev: need non-zero value
708: require(_locked.amount > 0, 'No existing lock found');
720: require(_value > 0); // dev: need non-zero value
754: assert(_value > 0); // dev: need non-zero value
755: require(_locked.amount > 0, 'No existing lock found');
770: require(_locked.amount > 0, 'Nothing is locked');
Instances (59):
File: contracts/Core/SwapPair.sol
22: uint public totalSupply = 0;
64: uint public index0 = 0;
65: uint public index1 = 0;
268: for (uint i = 0; i < _prices.length; i++) {
284: uint nextIndex = 0;
285: uint index = 0;
400: for (uint i = 0; i < 255; i++) {
File: contracts/periphery/Bribe.sol
108: uint lower = 0;
140: uint lower = 0;
172: uint lower = 0;
235: for (uint i = 0; i < tokens.length; i++) {
251: for (uint i = 0; i < tokens.length; i++) {
370: uint reward = 0;
File: contracts/periphery/Gauge.sol
162: uint lower = 0;
194: uint lower = 0;
226: uint lower = 0;
299: for (uint i = 0; i < tokens.length; i++) {
434: uint reward = 0;
494: uint tokenId = 0;
File: contracts/periphery/Multiswap.sol
45: for (uint i = 0; i < length; ++i) {
58: for (uint i = 0; i < length; ++i) {
73: uint weightSum = 0;
75: for (uint i = 0; i < length; ++i) {
File: contracts/periphery/Voter.sol
149: uint256 _totalWeight = 0;
150: for (uint i = 0; i < _gaugeVoteCnt; i++) {
179: for (uint i = 0; i < _gaugeCnt; i++) {
190: uint256 _totalVoteWeight = 0;
191: uint256 _totalWeight = 0;
192: uint256 _usedWeight = 0;
194: for (uint i = 0; i < _gaugeCnt; i++) {
198: for (uint i = 0; i < _gaugeCnt; i++) {
309: for (uint i = 0; i < _gauges.length; i++) {
352: for (uint i = 0; i < _gauges.length; i++) {
363: for (uint i = 0; i < _bribes.length; i++) {
374: for (uint i = 0; i < _fees.length; i++) {
382: for (uint i = 0; i < _gauges.length; i++) {
415: for (uint x = 0; x < _gauges.length; x++) {
File: contracts/periphery/VotingEscrow.sol
477: int128 old_dslope = 0;
478: int128 new_dslope = 0;
515: uint block_slope = 0; // dblock/dt
525: for (uint i = 0; i < 255; ++i) {
529: int128 d_slope = 0;
539: last_point.bias = 0;
543: last_point.slope = 0;
567: last_point.slope = 0;
570: last_point.bias = 0;
815: uint _min = 0;
817: for (uint i = 0; i < 128; ++i) {
845: last_point.bias = 0;
885: uint _min = 0;
887: for (uint i = 0; i < 128; ++i) {
905: uint d_block = 0;
906: uint d_t = 0;
939: for (uint i = 0; i < 255; ++i) {
941: int128 d_slope = 0;
956: last_point.bias = 0;
983: uint dt = 0;
File: test/Fees.t.sol
192: for (uint i = 0; i < num; i++) {
File: test/Voter.t.sol
480: for (uint i = 0; i < num; i++) {
Instances (10):
File: contracts/periphery/Bribe.sol
111: uint center = upper - (upper - lower) / 2; // ceil, avoiding overflow
143: uint center = upper - (upper - lower) / 2; // ceil, avoiding overflow
175: uint center = upper - (upper - lower) / 2; // ceil, avoiding overflow
File: contracts/periphery/Gauge.sol
165: uint center = upper - (upper - lower) / 2; // ceil, avoiding overflow
197: uint center = upper - (upper - lower) / 2; // ceil, avoiding overflow
229: uint center = upper - (upper - lower) / 2; // ceil, avoiding overflow
File: contracts/periphery/VotingEscrow.sol
822: uint _mid = (_min + _max + 1) / 2;
892: uint _mid = (_min + _max + 1) / 2;
File: test/Multiswap.t.sol
79: uint256 amount1 = daiToSwap / 2;
80: uint256 amount2 = daiToSwap / 2;
Use uint256(1) and uint256(2) for true/false to avoid a Gwarmaccess (100 gas), and to avoid Gsset (20000 gas) when changing from ‘false’ to ‘true’, after having been ‘true’ in the past. See source.
Instances (15):
File: contracts/Core/SwapFactory.sol
8: bool public isPaused;
13: mapping(address => mapping(address => mapping(bool => address))) public getPair;
15: mapping(address => bool) public isPair; // simplified check if its a pair, given that `stable` flag might not be available in peripherals
21: bool internal _temp2;
File: contracts/Core/SwapPair.sol
20: bool public immutable stable;
File: contracts/periphery/Bribe.sol
29: mapping(address => bool) public isReward;
File: contracts/periphery/Gauge.sol
42: mapping(address => bool) public isReward;
File: contracts/periphery/Voter.sol
37: mapping(address => bool) public isGauge;
38: mapping(address => bool) public isLive; // gauge => status (live or not)
40: mapping(address => bool) public isWhitelisted;
41: mapping(address => mapping(address => bool)) public isReward;
42: mapping(address => mapping(address => bool)) public isBribe;
File: contracts/periphery/VotingEscrow.sol
64: mapping(uint => bool) public voted;
90: mapping(address => mapping(address => bool)) internal ownerToOperators;
93: mapping(bytes4 => bool) internal supportedInterfaces;
Source Instead of using error strings, to reduce deployment and runtime cost, you should use Custom Errors. This would save both deployment and runtime cost.
Instances (33):
File: contracts/Core/SwapFactory.sol
27: require(msg.sender == admin, "Voter: only admin");
63: require(msg.sender == admin, "SwapFactory: only admin");
68: require(msg.sender == admin && _admin != address(0), "SwapFactory; wrong input parameters");
File: contracts/periphery/Bribe.sol
426: require(IVoter(voter).isBribe(address(this), token), "rewards tokens must be whitelisted");
427: require(rewards.length < MAX_REWARD_TOKENS, "too many rewards tokens");
447: require(rewardRate[token] <= balance / DURATION, "Provided reward too high");
File: contracts/periphery/Gauge.sol
539: require(IVoter(voter).isReward(address(this), token), "rewards tokens must be whitelisted");
540: require(rewards.length < MAX_REWARD_TOKENS, "too many rewards tokens");
560: require(rewardRate[token] <= balance / DURATION, "Provided reward too high");
File: contracts/periphery/Minter.sol
84: require(block.timestamp >= last_epoch + 26 weeks, "must wait next period");
136: require(_token.transfer(address(_ve_dist), _growth), "growth transfer failed");
File: contracts/periphery/Multiswap.sol
37: require(length > 1 && length <= 5 && _weights.length == length, "length");
38: require(_assertWeights(_weights), "wrong weights");
44: require(msg.value > 0, "no ETH sent");
54: require(_amount > 0, "no tokens sent");
56: require(transferFromSuccess, "transferFrom failed");
File: contracts/periphery/Voter.sol
64: require(msg.sender == admin, "Voter: only admin");
112: require(_admin != address(0), "zero address");
125: require(isLive[_gauge], "gauge is not live");
132: require(!isLive[_gauge], "gauge is live");
139: require(_activePeriod() > lastVote[_tokenId], "voted recently");
227: require(_activePeriod() > lastVote[tokenId], "already voted");
228: require(_nextPeriod() < _lockEnd, "lock expires soon");
248: require(ISwapFactory(factory).isPair(_pair), "!pair");
249: require(gauges[_pair] == address(0x0), "exists");
251: require(isWhitelisted[_tokenA] && isWhitelisted[_tokenB], "!whitelisted");
File: contracts/periphery/VotingEscrow.sol
311: require(attachments[_tokenId] == 0 && !voted[_tokenId], "attached");
383: require(retval == IERC721Receiver.onERC721Received.selector, "ERC721: transfer rejected");
674: require(attachments[_from] == 0 && !voted[_from], "attached");
781: require(attachments[_tokenId] == 0 && !voted[_tokenId], "attached");
784: require(block.timestamp >= _locked.end, "The lock didn't expire");
854: require(idToOwner[_tokenId] != address(0), "Query for nonexistent token");
1032: require(_isApprovedOrOwner(msg.sender, _tokenId), "caller is not owner nor approved");
Saves 5 gas per loop
Instances (29):
File: contracts/Core/SwapPair.sol
268: for (uint i = 0; i < _prices.length; i++) {
400: for (uint i = 0; i < 255; i++) {
497: keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, nonces[owner]++, deadline))
File: contracts/periphery/Bribe.sol
235: for (uint i = 0; i < tokens.length; i++) {
251: for (uint i = 0; i < tokens.length; i++) {
289: for (uint i = _startIndex; i < _endIndex; i++) {
314: for (uint i; i < length; i++) {
336: for (uint i = _startIndex; i <= _endIndex - 1; i++) {
373: for (uint i = _startIndex; i <= _endIndex - 1; i++) {
File: contracts/periphery/Gauge.sol
299: for (uint i = 0; i < tokens.length; i++) {
351: for (uint i = _startIndex; i < _endIndex; i++) {
378: for (uint i; i < length; i++) {
400: for (uint i = _startIndex; i <= _endIndex - 1; i++) {
437: for (uint i = _startIndex; i <= _endIndex-1; i++) {
File: contracts/periphery/Voter.sol
150: for (uint i = 0; i < _gaugeVoteCnt; i++) {
179: for (uint i = 0; i < _gaugeCnt; i++) {
194: for (uint i = 0; i < _gaugeCnt; i++) {
198: for (uint i = 0; i < _gaugeCnt; i++) {
309: for (uint i = 0; i < _gauges.length; i++) {
315: for (uint i = start; i < end; i++) {
352: for (uint i = 0; i < _gauges.length; i++) {
363: for (uint i = 0; i < _bribes.length; i++) {
374: for (uint i = 0; i < _fees.length; i++) {
382: for (uint i = 0; i < _gauges.length; i++) {
409: for (uint x = start; x < finish; x++) {
415: for (uint x = 0; x < _gauges.length; x++) {
File: contracts/periphery/VotingEscrow.sol
1019: digits++;
File: test/Fees.t.sol
192: for (uint i = 0; i < num; i++) {
File: test/Voter.t.sol
480: for (uint i = 0; i < num; i++) {
If needed, the values can be read from the verified contract source code, or if there are multiple values there can be a single getter function that returns a tuple of the values of all currently-public constants. Saves 3406-3606 gas in deployment gas due to the compiler not having to create non-payable getter functions for deployment calldata, not having to store the bytes of the value outside of where it's used, and not adding another entry to the method ID table
Instances (7):
File: contracts/Core/SwapPair.sol
17: uint8 public constant decimals = 18;
File: contracts/periphery/Bribe.sol
15: uint public constant DURATION = 7 days; // rewards are released over 7 days
16: uint public constant PRECISION = 10 ** 18;
17: uint public constant MAX_REWARD_TOKENS = 16; // max number of reward tokens that can be added
File: contracts/periphery/VotingEscrow.sol
67: string constant public name = "veNFT";
68: string constant public symbol = "veNFT";
69: uint8 constant public decimals = 18;
Issue | Instances | |
---|---|---|
[NC-1] | Return values of approve() not checked |
41 |
[NC-2] | constant s should be defined rather than using magic numbers |
5 |
Not all IERC20 implementations revert()
when there's a failure in approve()
. The function signature has a boolean return value and they indicate errors that way instead. By not checking the return value, operations that should have marked as failed, may potentially go through without actually approving anything
Instances (41):
File: contracts/periphery/Minter.sol
73: // _token.approve(address(_ve), type(uint).max);
141: _token.approve(address(_voter), weekly);
File: contracts/periphery/Multiswap.sol
57: IERC20(_token).approve(router, _amount);
File: contracts/periphery/Voter.sol
254: IERC20(base).approve(_gauge, type(uint).max);
File: contracts/periphery/VotingEscrow.sol
1037: approve(address(0), _tokenId);
File: test/Fees.t.sol
28: USDC.approve(address(_router), type(uint).max);
29: DAI.approve(address(_router), type(uint).max);
62: USDC.approve(address(_router), type(uint).max);
78: USDC.approve(address(_router), type(uint).max);
91: USDC.approve(address(_router), type(uint).max);
106: USDC.approve(address(_router), type(uint).max);
190: DAI.approve(address(_router), daiAmount * num);
191: USDC.approve(address(_router), usdcAmount * num);
File: test/Multiswap.t.sol
33: DAI.approve(address(_router), type(uint).max);
34: USDC.approve(address(_router), type(uint).max);
89: DAI.approve(address(_multiswap), daiToSwap);
File: test/Router.t.sol
45: DAI.approve(router, type(uint).max);
46: USDC.approve(router, type(uint).max);
72: DAI.approve(router, type(uint).max);
73: USDC.approve(router, type(uint).max);
File: test/Voter.t.sol
52: token.approve(address(_voter), fee * 3);
179: ISwapPair(pair).approve(address(_router), maxLp);
223: ISwapPair(pair).approve(gauge, maxLp);
225: ISwapPair(pair).approve(address(_router), maxLp);
259: ISwapPair(pair).approve(gauge, maxLp);
261: ISwapPair(pair).approve(address(_router), maxLp);
306: ISwapPair(pair).approve(gauge, maxLp);
308: ISwapPair(pair).approve(address(_router), maxLp);
333: ISwapPair(pair).approve(swapGauge, balanceThis);
348: ISwapPair(pair).approve(swapGauge, balanceAlice);
400: token.approve(swapGauge, 100 * 1e18);
453: DAI.approve(address(_router), amountA);
454: USDC.approve(address(_router), amountB);
478: DAI.approve(address(_router), daiAmount * num);
479: USDC.approve(address(_router), usdcAmount * num);
511: token.approve(address(_ve), amount);
File: test/VotingEscrow.t.sol
22: _token.approve(votingEscrow, 110e18);
31: _token.approve(votingEscrow, 100e18);
39: _token.approve(votingEscrow, 100e18);
70: _token.approve(votingEscrow, _value);
76: _token.approve(votingEscrow, _value);
Instances (5):
File: test/Multiswap.t.sol
77: weights.push(5000);
78: weights.push(5000);
113: _weights.push(5000);
114: _weights.push(5000);
146: __weights.push(2000);
Issue | Instances | |
---|---|---|
[L-1] | Unsafe ERC20 operation(s) | 47 |
[L-2] | Do not use deprecated library functions | 3 |
[L-3] | abi.encodePacked() should not be used with dynamic types when passing the result to a hash function such as keccak256() |
1 |
Instances (47):
File: contracts/periphery/Minter.sol
136: require(_token.transfer(address(_ve_dist), _growth), "growth transfer failed");
141: _token.approve(address(_voter), weekly);
File: contracts/periphery/Multiswap.sol
55: (bool transferFromSuccess) = IERC20(_token).transferFrom(msg.sender, address(this), _amount);
57: IERC20(_token).approve(router, _amount);
File: contracts/periphery/Voter.sol
254: IERC20(base).approve(_gauge, type(uint).max);
File: contracts/periphery/VotingEscrow.sol
641: assert(IERC20(token).transferFrom(from, address(this), _value));
796: assert(IERC20(token).transfer(msg.sender, value));
File: test/Fees.t.sol
28: USDC.approve(address(_router), type(uint).max);
29: DAI.approve(address(_router), type(uint).max);
62: USDC.approve(address(_router), type(uint).max);
78: USDC.approve(address(_router), type(uint).max);
91: USDC.approve(address(_router), type(uint).max);
106: USDC.approve(address(_router), type(uint).max);
190: DAI.approve(address(_router), daiAmount * num);
191: USDC.approve(address(_router), usdcAmount * num);
File: test/Multiswap.t.sol
33: DAI.approve(address(_router), type(uint).max);
34: USDC.approve(address(_router), type(uint).max);
89: DAI.approve(address(_multiswap), daiToSwap);
File: test/Router.t.sol
45: DAI.approve(router, type(uint).max);
46: USDC.approve(router, type(uint).max);
72: DAI.approve(router, type(uint).max);
73: USDC.approve(router, type(uint).max);
File: test/Voter.t.sol
52: token.approve(address(_voter), fee * 3);
179: ISwapPair(pair).approve(address(_router), maxLp);
223: ISwapPair(pair).approve(gauge, maxLp);
225: ISwapPair(pair).approve(address(_router), maxLp);
259: ISwapPair(pair).approve(gauge, maxLp);
261: ISwapPair(pair).approve(address(_router), maxLp);
306: ISwapPair(pair).approve(gauge, maxLp);
308: ISwapPair(pair).approve(address(_router), maxLp);
333: ISwapPair(pair).approve(swapGauge, balanceThis);
341: DAI.transfer(alice, 100_000e18);
342: USDC.transfer(alice, 100_000e6);
348: ISwapPair(pair).approve(swapGauge, balanceAlice);
400: token.approve(swapGauge, 100 * 1e18);
453: DAI.approve(address(_router), amountA);
454: USDC.approve(address(_router), amountB);
478: DAI.approve(address(_router), daiAmount * num);
479: USDC.approve(address(_router), usdcAmount * num);
511: token.approve(address(_ve), amount);
File: test/VotingEscrow.t.sol
22: _token.approve(votingEscrow, 110e18);
31: _token.approve(votingEscrow, 100e18);
38: _token.transfer(nonReceiver, 100e18);
39: _token.approve(votingEscrow, 100e18);
70: _token.approve(votingEscrow, _value);
76: _token.approve(votingEscrow, _value);
93: _ve.transferFrom(address(this),admin,1);
Instances (3):
File: contracts/periphery/Gauge.sol
122: _safeApprove(_token0, bribe, _fees0);
129: _safeApprove(_token1, bribe, _fees1);
580: function _safeApprove(address token, address spender, uint256 value) internal {
[L-3] abi.encodePacked()
should not be used with dynamic types when passing the result to a hash function such as keccak256()
Use abi.encode()
instead which will pad items to 32 bytes, which will prevent hash collisions (e.g. abi.encodePacked(0x123,0x456)
=> 0x123456
=> abi.encodePacked(0x1,0x23456)
, but abi.encode(0x123,0x456)
=> 0x0...1230...456
). "Unless there is a compelling reason, abi.encode
should be preferred". If there is only one argument to abi.encodePacked()
it can often be cast to bytes()
or bytes32()
instead.
If all arguments are strings and or bytes, bytes.concat()
should be used instead
Instances (1):
File: contracts/Core/SwapFactory.sol
85: bytes32 salt = keccak256(abi.encodePacked(token0, token1, stable)); // notice salt includes stable as well, 3 parameters