Platform: Code4rena
Start Date: 26/07/2022
Pot Size: $75,000 USDC
Total HM: 29
Participants: 179
Period: 6 days
Judge: LSDan
Total Solo HM: 6
Id: 148
League: ETH
Rank: 88/179
Findings: 1
Award: $94.66
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: JohnSmith
Also found by: 0x1f8b, 0xA5DF, 0xDjango, 0xKitsune, 0xLovesleep, 0xNazgul, 0xSmartContract, 0xmatt, 0xsam, Aymen0909, Bnke0x0, CRYP70, Chandr, Chinmay, CodingNameKiki, Deivitto, Dravee, ElKu, Fitraldys, Funen, GalloDaSballo, Green, IllIllI, JC, Jmaxmanblue, Junnon, Kaiziron, Kenshin, Krow10, Maxime, Migue, MiloTruck, Noah3o6, NoamYakov, Randyyy, RedOneN, ReyAdmirado, Rohan16, Rolezn, Ruhum, Sm4rty, StyxRave, TomJ, Tomio, _Adam, __141345__, ajtra, ak1, apostle0x01, asutorufos, async, benbaessler, brgltd, c3phas, cRat1st0s, carlitox477, delfin454000, djxploit, durianSausage, ellahi, erictee, fatherOfBlocks, gerdusx, gogo, hyh, jayfromthe13th, jayphbee, joestakey, kaden, kenzo, kyteg, ladboy233, lucacez, m_Rassska, mics, minhquanym, oyc_109, pfapostol, rbserver, reassor, rfa, robee, rokinot, sach1r0, saian, samruna, sashik_eth, simon135, supernova, tofunmi, zuhaibmohd
94.6571 USDC - $94.66
If a function modifier such as onlyOwner is used, the function will revert if a normal user tries to pay the function. Marking the function as payable will lower the gas cost for legitimate callers because the compiler will not include checks for whether a payment was provided. The extra opcodes avoided are CALLVALUE
(2),DUP1
(3),ISZERO
(3),PUSH2
(3),JUMPI
(10),PUSH1
(3),DUP1
(3),REVERT
(0),JUMPDEST
(1),POP
(2), which costs an average of about 21 gas per call to the function, in addition to the extra deployment cost
There are 2 instances of this issue:
File: /contracts/governance/GolomToken.sol 36: function mint(address _account, uint256 _amount) external onlyMinter {
https://github.com/code-423n4/2022-07-golom/blob/main/contracts/governance/GolomToken.sol#L36
File: /contracts/rewards/RewardDistributor.sol 98: function addFee(address[2] memory addr, uint256 fee) public onlyTrader {
https://github.com/code-423n4/2022-07-golom/blob/main/contracts/rewards/RewardDistributor.sol#L98
PUBLIC
FUNCTIONS NOT CALLED BY THE CONTRACT SHOULD BE DECLARED EXTERNAL
INSTEADFor all the public functions, the input parameters are copied to memory automatically, and it costs gas. If your function is only called externally, then you should explicitly mark it as external. External function’s parameters are not copied into memory but are read from calldata directly. This small optimization in your solidity code can save you a lot of gas when the function input parameters are huge.
There are 12 instances of this issue:
File: /contracts/rewards/RewardDistributor.sol 98: function addFee(address[2] memory addr, uint256 fee) public onlyTrader { 141: function traderClaim(address addr, uint256[] memory epochs) public { 155: function exchangeClaim(address addr, uint256[] memory epochs) public { 172: function multiStakerClaim(uint256[] memory tokenids, uint256[] memory epochs) public { 215: function stakerRewards(uint256 tokenid) public view returns ( 254: function traderRewards(address addr) public view returns ( 269: function exchangeRewards(address addr) public view returns (
https://github.com/code-423n4/2022-07-golom/blob/main/contracts/rewards/RewardDistributor.sol#L98
File: /contracts/core/GolomTrader.sol 203: function fillAsk( 279: function fillBid( 312: function cancelOrder(Order calldata o) public nonReentrant { 334: function fillCriteriaBid(
https://github.com/code-423n4/2022-07-golom/blob/main/contracts/core/GolomTrader.sol#L203
File: /contracts/vote-escrow/VoteEscrowDelegation.sol 185: function getPriorVotes(uint256 tokenId, uint256 blockNumber) public view returns (uint256) {
One of most the expensive opcodes is SLOAD
. In order to save gas from checking the value of storage
-located variable they can be cached in memory
. That way the MLOAD
opcode is used each time we want to access the variable which is much cheaper than SLOAD
.
There are 8 instances of this issue:
File: /contracts/core/GolomTrader.sol 189: if (filled[hashStruct] >= o.tokenAmt) { ... 193: return (3, hashStruct, o.tokenAmt - filled[hashStruct]);
Cache filled[hashStruct]
https://github.com/code-423n4/2022-07-golom/blob/main/contracts/core/GolomTrader.sol#L189-L193
File: /contracts/core/GolomTrader.sol 382: WETH.transferFrom(o.signer, address(this), o.totalAmt * amount); 383: WETH.withdraw(o.totalAmt * amount);
Cache WETH
https://github.com/code-423n4/2022-07-golom/blob/main/contracts/core/GolomTrader.sol#L382-L383
File: /contracts/rewards/RewardDistributor.sol 100: if (rewardToken.totalSupply() > 1000000000 * 10**18) { ... 112: uint256 tokenToEmit = (dailyEmission * (rewardToken.totalSupply() - rewardToken.balanceOf(address(ve)))) / 113: rewardToken.totalSupply(); 114: uint256 stakerReward = (tokenToEmit * rewardToken.balanceOf(address(ve))) / rewardToken.totalSupply();
Cache rewardToken.totalSupply()
and rewardToken.balanceOf(address(ve))
https://github.com/code-423n4/2022-07-golom/blob/main/contracts/rewards/RewardDistributor.sol#L100
File: /contracts/rewards/RewardDistributor.sol 173: require(address(ve) != address(0), ' VE not added yet'); 177: address tokenowner = ve.ownerOf(tokenids[0]); 181: require(tokenowner == ve.ownerOf(tokenids[tindex]), 'Can only claim for a single Address together'); 191: ve.balanceOfAtNFT(tokenids[tindex], epochBeginTime[1])) / 192: ve.totalSupplyAt(epochBeginTime[1]); 198: ve.totalSupplyAt(epochBeginTime[epochs[index]]); 203: ve.totalSupplyAt(epochBeginTime[epochs[index]]); 220: require(address(ve) != address(0), ' VE not added yet'); 233: ve.balanceOfAtNFT(tokenid, epochBeginTime[1])) / 234: ve.totalSupplyAt(epochBeginTime[1]); 239: (rewardStaker[index] * ve.balanceOfAtNFT(tokenid, epochBeginTime[index])) / 240: ve.totalSupplyAt(epochBeginTime[index]); 244: ve.balanceOfAtNFT(tokenid, epochBeginTime[index])) / 245: ve.totalSupplyAt(epochBeginTime[index]);
Cache ve
, ve.totalSupplyAt(epochBeginTime[epochs[index]])
and ve.balanceOfAtNFT(tokenid, epochBeginTime[index])) / ve.totalSupplyAt(epochBeginTime[index])
https://github.com/code-423n4/2022-07-golom/blob/main/contracts/rewards/RewardDistributor.sol#L173
File: /contracts/vote-escrow/VoteEscrowCore.sol 650: bool senderIsOwner = (idToOwner[_tokenId] == msg.sender);
Use owner
instead of idToOwner[_tokenId]
https://github.com/code-423n4/2022-07-golom/blob/main/contracts/vote-escrow/VoteEscrowCore.sol#L650
INTERNAL
and PRIVATE
FUNCTIONS ONLY CALLED ONCE CAN BE INLINED TO SAVE GASNot inlining costs 20 to 40 gas because of two extra JUMP
instructions and additional stack operations needed for function calls.
There are 2 instances of this issue:
File: /contracts/core/GolomTrader.sol 123: function _hashOrder(Order calldata o) private pure returns (bytes32) { 127: function _hashOrderinternal(Order calldata o, uint256[2] memory extra) private pure returns (bytes32) {
https://github.com/code-423n4/2022-07-golom/blob/main/contracts/core/GolomTrader.sol#L123
> 0
COSTS LESS GAS THAN != 0
WHEN USED ON A UINT
This change saves 3 gas per instance
There are 7 instances of this issue:
File: /contracts/vote-escrow/VoteEscrowCore.sol 701: if (_tokenId != 0) { 717: if (new_locked.end != 0) { 781: if (_tokenId != 0) { 797: if (_tokenId != 0) { 848: if (unlock_time != 0) { 860: if (_value != 0 && deposit_type != DepositType.MERGE_TYPE) { 1144: if (d_block != 0) {
https://github.com/code-423n4/2022-07-golom/blob/main/contracts/vote-escrow/VoteEscrowCore.sol#L701
If a variable is not set/initialized, it is assumed to have the default value (0, false, 0x0 etc depending on the data type). Explicitly initializing it with its default value is an anti-pattern and wastes gas.
There are 37 instances of this issue:
File: /contracts/core/GolomTrader.sol 415: for (uint256 i = 0; i < proof.length; i++) {
https://github.com/code-423n4/2022-07-golom/blob/main/contracts/core/GolomTrader.sol#L415
File: /contracts/rewards/RewardDistributor.sol 45: uint256 public epoch = 0; 142: uint256 reward = 0; 143: for (uint256 index = 0; index < epochs.length; index++) { 156: uint256 reward = 0; 157: for (uint256 index = 0; index < epochs.length; index++) { 175: uint256 reward = 0; 176: uint256 rewardEth = 0; 180: for (uint256 tindex = 0; tindex < tokenids.length; tindex++) { 183: for (uint256 index = 0; index < epochs.length; index++) { 222: uint256 reward = 0; 223: uint256 rewardEth = 0; 226: for (uint256 index = 0; index < epoch; index++) { 257: uint256 reward = 0; 258: for (uint256 index = 0; index < epoch; index++) { 272: uint256 reward = 0; 273: for (uint256 index = 0; index < epoch; index++) {
https://github.com/code-423n4/2022-07-golom/blob/main/contracts/rewards/RewardDistributor.sol#L45
File: /contracts/vote-escrow/VoteEscrowCore.sol 697: int128 old_dslope = 0; 698: int128 new_dslope = 0; 735: uint256 block_slope = 0; 745: for (uint256 i = 0; i < 255; ++i) { 749: int128 d_slope = 0; 1042: uint256 _min = 0; 1044: for (uint256 i = 0; i < 128; ++i) { 1113: uint256 _min = 0; 1115: for (uint256 i = 0; i < 128; ++i) { 1133: uint256 d_block = 0; 1134: uint256 d_t = 0; 1167: for (uint256 i = 0; i < 255; ++i) { 1169: int128 d_slope = 0; 1211: uint256 dt = 0;
https://github.com/code-423n4/2022-07-golom/blob/main/contracts/vote-escrow/VoteEscrowCore.sol#L697
File: /contracts/vote-escrow/VoteEscrowDelegation.sol 50: uint256 public MIN_VOTING_POWER_REQUIRED = 0; 147: uint256 lower = 0; 170: uint256 votes = 0; 171: for (uint256 index = 0; index < delegated.length; index++) { 188: uint256 votes = 0; 189: for (uint256 index = 0; index < delegatednft.length; index++) {
If needed, the value can be read from the verified contract source code. Savings are due to the compiler not having to create non-payable getter functions for deployment calldata, and not adding another entry to the method ID table
There are 4 instances of this issue:
File: /contracts/vote-escrow/VoteEscrowCore.sol 317: string public constant name = 'veNFT'; 318: string public constant symbol = 'veNFT'; 319: string public constant version = '1.0.0'; 320: uint8 public constant decimals = 18;
++I
costs less gas than I++
, especially when it's used in for-loops (--I
/I--
too). Saves 6 gas per instance
There are 11 instances of this issue:
File: /contracts/vote-escrow/VoteEscrowDelegation.sol 171: for (uint256 index = 0; index < delegated.length; index++) { 189: for (uint256 index = 0; index < delegatednft.length; index++) { 199: for (uint256 i; i < _array.length; i++) {
File: /contracts/core/GolomTrader.sol 415: for (uint256 i = 0; i < proof.length; i++) {
https://github.com/code-423n4/2022-07-golom/blob/main/contracts/core/GolomTrader.sol#L415
File: /contracts/rewards/RewardDistributor.sol 143: for (uint256 index = 0; index < epochs.length; index++) { 157: for (uint256 index = 0; index < epochs.length; index++) { 180: for (uint256 tindex = 0; tindex < tokenids.length; tindex++) { 183: for (uint256 index = 0; index < epochs.length; index++) { 226: for (uint256 index = 0; index < epoch; index++) { 258: for (uint256 index = 0; index < epoch; index++) { 273: for (uint256 index = 0; index < epoch; index++) {
https://github.com/code-423n4/2022-07-golom/blob/main/contracts/rewards/RewardDistributor.sol#L143
The overheads outlined below are PER LOOP, excluding the first loop
MLOAD
(3 gas)CALLDATALOAD
(3 gas) \There are 11 instances of this issue:
File: /contracts/vote-escrow/VoteEscrowDelegation.sol 171: for (uint256 index = 0; index < delegated.length; index++) { 189: for (uint256 index = 0; index < delegatednft.length; index++) { 199: for (uint256 i; i < _array.length; i++) {
File: /contracts/core/GolomTrader.sol 415: for (uint256 i = 0; i < proof.length; i++) {
https://github.com/code-423n4/2022-07-golom/blob/main/contracts/core/GolomTrader.sol#L415
File: /contracts/rewards/RewardDistributor.sol 143: for (uint256 index = 0; index < epochs.length; index++) { 157: for (uint256 index = 0; index < epochs.length; index++) { 180: for (uint256 tindex = 0; tindex < tokenids.length; tindex++) { 183: for (uint256 index = 0; index < epochs.length; index++) {
https://github.com/code-423n4/2022-07-golom/blob/main/contracts/rewards/RewardDistributor.sol#L143
The unchecked
keyword is new in solidity version 0.8.0, so this only applies to that version or higher, which these instances are. This saves 30-40 gas per loop
There are 15 instances of this issue:
File: /contracts/core/GolomTrader.sol 415: for (uint256 i = 0; i < proof.length; i++) {
https://github.com/code-423n4/2022-07-golom/blob/main/contracts/core/GolomTrader.sol#L415
File: /contracts/rewards/RewardDistributor.sol 143: for (uint256 index = 0; index < epochs.length; index++) { 157: for (uint256 index = 0; index < epochs.length; index++) { 180: for (uint256 tindex = 0; tindex < tokenids.length; tindex++) { 183: for (uint256 index = 0; index < epochs.length; index++) { 226: for (uint256 index = 0; index < epoch; index++) { 258: for (uint256 index = 0; index < epoch; index++) { 273: for (uint256 index = 0; index < epoch; index++) {
https://github.com/code-423n4/2022-07-golom/blob/main/contracts/rewards/RewardDistributor.sol#L143
File: /contracts/vote-escrow/VoteEscrowCore.sol 745: for (uint256 i = 0; i < 255; ++i) { 1044: for (uint256 i = 0; i < 128; ++i) { 1115: for (uint256 i = 0; i < 128; ++i) { 1167: for (uint256 i = 0; i < 255; ++i) {
https://github.com/code-423n4/2022-07-golom/blob/main/contracts/vote-escrow/VoteEscrowCore.sol#L745
File: /contracts/vote-escrow/VoteEscrowDelegation.sol 171: for (uint256 index = 0; index < delegated.length; index++) { 189: for (uint256 index = 0; index < delegatednft.length; index++) { 199: for (uint256 i; i < _array.length; i++) {
There are 2 instances of this issue:
File: /contracts/vote-escrow/VoteEscrowCore.sol 499: ownerToNFTokenCount[_to] += 1; 512: ownerToNFTokenCount[_from] -= 1;
https://github.com/code-423n4/2022-07-golom/blob/main/contracts/vote-escrow/VoteEscrowCore.sol#L499
"When using elements that are smaller than 32 bytes, your contract’s gas usage may be higher. This is because the EVM operates on 32 bytes at a time. Therefore, if the element is smaller than that, the EVM must use more operations in order to reduce the size of the element from 32 bytes to the desired size."
https://docs.soliditylang.org/en/v0.8.15/internals/layout_in_storage.html
Use a larger size then downcast where needed
There are 9 instances of this issue:
File: /contracts/vote-escrow/VoteEscrowCore.sol 261: int128 bias; 262: int128 slope; 271: int128 amount; 297: int128 internal constant iMAXTIME = 4 * 365 * 86400; 311: mapping(uint256 => int128) public slope_changes; 697: int128 old_dslope = 0; 698: int128 new_dslope = 0; 749: int128 d_slope = 0; 1169: int128 d_slope = 0;
https://github.com/code-423n4/2022-07-golom/blob/main/contracts/vote-escrow/VoteEscrowCore.sol#L261
x <= y
with x < y + 1
, and x >= y
with x > y - 1
.In the EVM, there is no opcode for >=
or <=
. When using greater than or equal, two operations are performed: >
and =
. Using strict comparison operators hence saves gas
There are 19 instances of this issue:
File: /contracts/core/GolomTrader.sol 189: if (filled[hashStruct] >= o.tokenAmt) { 212: o.totalAmt >= o.exchange.paymentAmt + o.prePayment.paymentAmt + o.refererrAmt + (o.totalAmt * 50) / 10000, 217: require(msg.value >= o.totalAmt * amount + p.paymentAmt, 'mgmtm'); 227: require(amountRemaining >= amount, 'order already filled'); 296: require(amountRemaining >= amount); 342: require(o.totalAmt >= o.exchange.paymentAmt + o.prePayment.paymentAmt + o.refererrAmt); 350: require(amountRemaining >= amount); 417: if (computedHash <= proofElement) { 455: require(distributorEnableDate <= block.timestamp, 'not allowed');
https://github.com/code-423n4/2022-07-golom/blob/main/contracts/core/GolomTrader.sol#L189
File: /contracts/governance/GolomToken.sol 69: require(minterEnableDate <= block.timestamp, 'GolomToken: wait for timelock');
https://github.com/code-423n4/2022-07-golom/blob/main/contracts/governance/GolomToken.sol#L69
File: /contracts/rewards/RewardDistributor.sol 292: require(traderEnableDate <= block.timestamp, 'RewardDistributor: time not over yet'); 309: require(voteEscrowEnableDate <= block.timestamp, 'RewardDistributor: time not over yet');
https://github.com/code-423n4/2022-07-golom/blob/main/contracts/rewards/RewardDistributor.sol#L292
File: /contracts/vote-escrow/VoteEscrowCore.sol 902: uint256 end = _locked0.end >= _locked1.end ? _locked0.end : _locked1.end; 946: require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max'); 999: require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max'); 1011: require(block.timestamp >= _locked.end, "The lock didn't expire"); 1046: if (_min >= _max) { 1050: if (point_history[_mid].blk <= _block) { 1110: assert(_block <= block.number); 1117: if (_min >= _max) { 1121: if (user_point_history[_tokenId][_mid].blk <= _block) { 1149: if (upoint.bias >= 0) { 1206: assert(_block <= block.number);
https://github.com/code-423n4/2022-07-golom/blob/main/contracts/vote-escrow/VoteEscrowCore.sol#L901
File: /contracts/vote-escrow/VoteEscrowDelegation.sol 73: require(this.balanceOfNFT(tokenId) >= MIN_VOTING_POWER_REQUIRED, 'VEDelegation: Need more voting power'); 138: if (checkpoints[nftId][nCheckpoints - 1].fromBlock <= blockNumber) {
Custom errors from Solidity 0.8.4 are cheaper than revert strings (cheaper deployment cost and runtime cost when the revert condition is met) while providing the same amount of information. In order to get rid of the multiple custom errors, a single universal custom error Exception(uint c)
can be used. It would accept a single parameter that represents an error code used to make a reference to an off-chain dictionary of the errors' descriptions.
There are 46 instances of this issue:
File: /contracts/governance/GolomToken.sol 24: require(msg.sender == minter, 'GolomToken: only reward distributor can enable'); 43: require(!isAirdropMinted, 'already minted'); 51: require(!isGenesisRewardMinted, 'already minted'); 69: require(minterEnableDate <= block.timestamp, 'GolomToken: wait for timelock');
https://github.com/code-423n4/2022-07-golom/blob/main/contracts/governance/GolomToken.sol#L24
File: /contracts/vote-escrow/VoteEscrowDelegation.sol 72: require(ownerOf(tokenId) == msg.sender, 'VEDelegation: Not allowed'); 73: require(this.balanceOfNFT(tokenId) >= MIN_VOTING_POWER_REQUIRED, 'VEDelegation: Need more voting power'); 99: require(_delegatedTokenIds.length < 500, 'VVDelegation: Cannot stake more'); 130: require(blockNumber < block.number, 'VEDelegation: not yet determined'); 186: require(blockNumber < block.number, 'VEDelegation: not yet determined'); 211: require(ownerOf(tokenId) == msg.sender, 'VEDelegation: Not allowed'); 239: require(attachments[_tokenId] == 0 && !voted[_tokenId], 'attached');
File: /contracts/rewards/RewardDistributor.sol 173: require(address(ve) != address(0), ' VE not added yet'); 181: require(tokenowner == ve.ownerOf(tokenids[tindex]), 'Can only claim for a single Address together'); 184: require(epochs[index] < epoch, 'cant claim for future epochs'); 185: require(claimed[tokenids[tindex]][epochs[index]] == 0, 'cant claim if already claimed'); 220: require(address(ve) != address(0), ' VE not added yet'); 292: require(traderEnableDate <= block.timestamp, 'RewardDistributor: time not over yet'); 309: require(voteEscrowEnableDate <= block.timestamp, 'RewardDistributor: time not over yet');
https://github.com/code-423n4/2022-07-golom/blob/main/contracts/rewards/RewardDistributor.sol#L173
File: /contracts/core/GolomTrader.sol 177: require(signaturesigner == o.signer, 'invalid signature'); 211: require( 212: o.totalAmt >= o.exchange.paymentAmt + o.prePayment.paymentAmt + o.refererrAmt + (o.totalAmt * 50) / 10000, //19 213: 'amt not matching' //17 214: ); 217: require(msg.value >= o.totalAmt * amount + p.paymentAmt, 'mgmtm'); 222: require(o.orderType == 0, 'invalid orderType'); 226: require(status == 3, 'order not valid'); 227: require(amountRemaining >= amount, 'order already filled'); 235: require(amount == 1, 'only 1 erc721 at 1 time'); 299: require(amount == 1, 'only 1 erc721 at 1 time'); 359: require(amount == 1, 'only 1 erc721 at 1 time'); 426: revert('invalid proof'); 455: require(distributorEnableDate <= block.timestamp, 'not allowed');
https://github.com/code-423n4/2022-07-golom/blob/main/contracts/core/GolomTrader.sol#L177
File: /contracts/vote-escrow/VoteEscrowCore.sol 538: require(attachments[_tokenId] == 0 && !voted[_tokenId], 'attached'); 608: revert('ERC721: transfer to non ERC721Receiver implementer'); 894: require(attachments[_from] == 0 && !voted[_from], 'attached'); 928: require(_locked.amount > 0, 'No existing lock found'); 929: require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw'); 945: require(unlock_time > block.timestamp, 'Can only lock until time in the future'); 946: require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max'); 982: require(_locked.amount > 0, 'No existing lock found'); 983: require(_locked.end > block.timestamp, 'Cannot add to expired lock. Withdraw'); 996: require(_locked.end > block.timestamp, 'Lock expired'); 997: require(_locked.amount > 0, 'Nothing is locked'); 998: require(unlock_time > _locked.end, 'Can only increase lock duration'); 999: require(unlock_time <= block.timestamp + MAXTIME, 'Voting lock can be 4 years max'); 1008: require(attachments[_tokenId] == 0 && !voted[_tokenId], 'attached'); 1011: require(block.timestamp >= _locked.end, "The lock didn't expire"); 1082: require(idToOwner[_tokenId] != address(0), 'Query for nonexistent token'); 1227: require(_isApprovedOrOwner(msg.sender, _tokenId), 'caller is not owner nor approved');
https://github.com/code-423n4/2022-07-golom/blob/main/contracts/vote-escrow/VoteEscrowCore.sol#L538
Remove duplicate code in order to reduce contract's size and deployment cost
There is 1 instances of this issue:
File: /contracts/vote-escrow/VoteEscrowCore.sol 467: if (current_count == current_index) { 468: // update ownerToNFTokenIdList 469: ownerToNFTokenIdList[_from][current_count] = 0; 470: // update tokenToOwnerIndex 471: tokenToOwnerIndex[_tokenId] = 0; 472: } else { 473: uint256 lastTokenId = ownerToNFTokenIdList[_from][current_count]; 474: 475: // Add 476: // update ownerToNFTokenIdList 477: ownerToNFTokenIdList[_from][current_index] = lastTokenId; 478: // update tokenToOwnerIndex 479: tokenToOwnerIndex[lastTokenId] = current_index; 480: 481: // Delete //bonus изнеси извън тва to reduce deployment 482: // update ownerToNFTokenIdList 483: ownerToNFTokenIdList[_from][current_count] = 0; 484: // update tokenToOwnerIndex 485: tokenToOwnerIndex[_tokenId] = 0; 486: }
^ Remove the first check and move lines 468-471 and 482-485 outside the if
check' parentheses
Result:
File: /contracts/vote-escrow/VoteEscrowCore.sol 467: if (current_count != current_index) { 468: uint256 lastTokenId = ownerToNFTokenIdList[_from][current_count]; 469: 470: // Add 471: // update ownerToNFTokenIdList 472: ownerToNFTokenIdList[_from][current_index] = lastTokenId; 473: // update tokenToOwnerIndex 474: tokenToOwnerIndex[lastTokenId] = current_index; 475: } 476 477: // update ownerToNFTokenIdList 478: ownerToNFTokenIdList[_from][current_count] = 0; 479: // update tokenToOwnerIndex 480: tokenToOwnerIndex[_tokenId] = 0;