Skip to content

Instantly share code, notes, and snippets.

@Picodes
Created October 18, 2022 20:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Picodes/51789d48e3a3c9246a48bb490d688343 to your computer and use it in GitHub Desktop.
Save Picodes/51789d48e3a3c9246a48bb490d688343 to your computer and use it in GitHub Desktop.

Report

Gas Optimizations

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

[GAS-1] Cache array length outside of loop

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++) {

[GAS-2] Use != 0 instead of > 0 for unsigned integer comparison

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');

[GAS-3] Don't initialize variables with default value

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++) {

[GAS-4] Use shift Right/Left instead of division/multiplication if possible

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;

[GAS-5] Using bools for storage incurs overhead

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;

[GAS-6] Use Custom Errors

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");

[GAS-7] ++i costs less gas than i++, especially when it's used in for-loops (--i/i-- too)

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++) {

[GAS-8] Using private rather than public for constants, saves gas

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;

Non Critical Issues

Issue Instances
[NC-1] Return values of approve() not checked 41
[NC-2] constants should be defined rather than using magic numbers 5

[NC-1] Return values of approve() not checked

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);

[NC-2] constants should be defined rather than using magic numbers

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);

Low Issues

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

[L-1] Unsafe ERC20 operation(s)

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);

[L-2] Do not use deprecated library functions

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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment