I've been wreaking my brain on this for a while, could use some help. Bottomline, the newProposal
function throws an VM Exception while processing transaction: invalid opcode
error. The puzzling thing is that this function was working fine with Solidity 0.5, but not with 0.6. Here is what I've attempted so far, any further insight is greatly appreciated.
- According to the breaking changes in Solidity 0.6, I suspect that the issue is about the resizing of the
proposals
array to add a newProposal
struct, which is somewhat supported by this issue.
- Member-access to length of arrays is now always read-only, even for storage arrays. It is no longer possible to resize storage arrays by assigning a new value to their length. Use push(), push(value) or pop() instead, or assign a full array, which will of course overwrite the existing content. The reason behind this is to prevent storage collisions of gigantic storage arrays.
So I have attempted a number of variations here (i.e., proposals.push()
, hard coding proposalID
). No luck. I don't believe the struct and its properties are the problem, but I can't be 100% sure of that either. So I feel like I'm missing something relatively obvious here, and I thank you for any assistance.
The function that returns an invalid opCode
error
/**
* Add Proposal
*
* Propose to send `weiAmount / 1e18` ether to `beneficiary` for `jobDescription`. `transactionBytecode ? Contains : Does not contain` code.
*
* @param beneficiary who to send the ether to
* @param weiAmount amount of ether to send, in wei
* @param jobDescription Description of job
* @param transactionBytecode bytecode of transaction
*/
function newProposal(
address beneficiary,
uint weiAmount,
string memory jobDescription,
bytes memory transactionBytecode
)
public onlyShareholders
returns (uint proposalID)
{
proposalID = proposals.length+1; //I suspect the problem is here...
// I've tried proposals.push(); proposalID = proposals.length; instead, no luck
Proposal storage p = proposals[proposalID]; //...or here
p.recipient = beneficiary;
p.amount = weiAmount;
p.description = jobDescription;
p.proposalHash = keccak256(abi.encodePacked(beneficiary, weiAmount, transactionBytecode));
p.minExecutionDate = now + debatingPeriodInMinutes * 1 minutes;
p.executed = false;
p.proposalPassed = false;
p.numberOfVotes = 0;
emit ProposalAdded(proposalID, beneficiary, weiAmount, jobDescription);
numProposals = proposalID+1;
return proposalID;
}
The Proposal
struct and proposals
array
Proposal[] public proposals;
struct Proposal {
address recipient;
uint amount;
string description;
uint minExecutionDate;
bool executed;
bool proposalPassed;
uint numberOfVotes;
bytes32 proposalHash;
Vote[] votes;
mapping (address => bool) voted;
}
EDIT: This fixed it, see comments below with @goodvibration
proposalID = proposals.length;
proposals.push();
Proposal storage p = proposals[proposalID];