Solidity

將 array.length 設置為 0 會在solidity 0.5.0 上觸發錯誤

  • May 22, 2019

為什麼將 array.length 設置為 0 會觸發錯誤?

我有一個函式可以從映射中的動態結構數組中刪除一個元素,如下所示:

mapping(address => MyStruct[]) public structs;

我的問題是,如果我嘗試將長度設置為 0,則會觸發此錯誤:VM Exception while processing transaction: invalid opcode

structs[_user].length = 0; // will trigger an error !

但是: structs[_user].length = 1;會正常工作。

它在這樣的函式內部:

function _burn(uint index) internal {

 require(index < array.length);

 array[index] = array[array.length-1];
 delete array[array.length-1];

 // when array.length is set to 0 it doesn't work:

 array.length = array.length - 1; // doesn't work if array.length = 1

 array.length = 0;  // doesn't work

 // when array.length is set to a value > 0 it works:

 array.length = 1;  // works

 array.length = 2; //  works

}

我嘗試了至少 45 個小時,卻不知道為什麼會這樣!如果您遇到此問題或知道如何處理它,我們將不勝感激。

PS:我使用的是solidity 0.5.2

這是整個程式碼:

// ----  Redeem a Stake ------  //

function stakeclmidx (uint _stakeidx) public {
require(_stakeidx >= 0);

Stake storage _stake = stakes[msg.sender][_stakeidx];

// See if the stake is over
require(block.number > _stake.endBlock);

require(_stake.amount > 0);

// transfer back token from contract to staker:
balances[address(this)] = balances[address(this)].sub(_stake.amount);

balances[msg.sender] = balances[msg.sender].add(_stake.amount);

emit Transfer(address(this), msg.sender, _stake.amount);
emit StakeClaimed(_stakeidx);

// deletes the stake
_deletestake(msg.sender, _stakeidx);

}

function _deletestake(address _staker,uint _index) internal {
require(_index < stakes[_staker].length);
stakes[_staker][_index] = stakes[_staker][stakes[_staker].length-1];
delete stakes[_staker][stakes[_staker].length-1];
stakes[_staker].length = stakes[_staker].length - 1;
// this last line is the one triggering the error
// it seems it triggers the error only when length value is set to 0
// stakes[_staker].length = 1; works !
// stakes[_staker].length = 2; works !
// stakes[_staker].length = 0; doesn't work !
}
// ----  Redeem a Stake ------  //

最好的祝福

您的程式碼中的問題如下行:

array[index] = array[array.length-1];

您不會將值分配給動態數組。你需要推。將其更改為

array.push(array[array.length-1]);

然後這應該工作。只需呼叫 reduce length 兩次。

請記住,減號是非常危險的。長度為零後,再次遞減不會報錯,會導致下溢,新數組會初始化為下溢長度。

pragma solidity ^0.5.0;

contract Arraytest{

   uint8[] public array ;

   constructor() public{
       for(uint8 counter=0; counter<2; counter++)
       {
           array.push(counter);
       }
   }

   event MESSAGE(uint _message);

   function reduceLength() public returns (uint8[] memory) {


           array.length--;
           emit MESSAGE(array.length);
           return array;



       //     array[index] = array[array.length-1];
       //     delete array[array.length-1];

       //   // when array.length is set to 0 it doesn't work:

       //   array.length = array.length - 1; // doesn't work if array.length = 1

       //   array.length = 0;  // doesn't work

       //   // when array.length is set to a value > 0 it works:

       //   array.length = 1;  // works

       //   array.length = 2; //  works

}

}

引用自:https://ethereum.stackexchange.com/questions/70907