My understanding is there is a gas refund for delete
and the idea is to encourage developers to remove garbage from contract states.
Consider this contract with a delete-enabled index of keys to mapped structs. The delete
operations in deleteVoter()
are not necessary for the function to work as required.
When the deletes
are included, gas is about 34056 for a deleteVoter()
. With the deletes
commented out, the contract is as functional as before, but deleteVoter()
only costs about 23926 gas. So, the deleteVoter()
function is more gas-efficient without the delete
garbage collection.
Q1: Why are the deletes
adding to the cost?
Q2: Am I missing something about optimizing the two delete
operations that seem to be adding to the gas cost?
Q3: Am I possibly missing the point of the gas refund? I expected the refund from the deletes
to bubble up into a net savings so the cost of deleteVoter()
would decrease. That is, incentivize garbage collection.
pragma solidity 0.4.11;
contract IterableMappingWithDelete {
struct Voter {
uint votesCast; // application data
uint voterListPointer; // structurally important
}
mapping(address => Voter) public voterStructs; // random access by key
address[] public voterList; // sequential access by row and count
function getVoterCount() public constant returns(uint voterCount) {return voterList.length;}
function isVoter(address voterId) public constant returns(bool isIndeed) {
if(voterList.length==0) return false;
return voterList[voterStructs[voterId].voterListPointer]==voterId;
}
function insertVoter(address voterId) public returns(bool success) {
if(isVoter(voterId)) throw;
voterStructs[voterId].voterListPointer = voterList.push(voterId) - 1;
return true;
}
function deleteVoter(address voterId) public returns(bool success) {
if(!isVoter(voterId)) throw;
uint rowToDelete = voterStructs[voterId].voterListPointer;
uint voterListLastRow = voterList.length-1;
address keyToMove = voterList[voterListLastRow];
voterStructs[keyToMove].voterListPointer = rowToDelete;
voterList[rowToDelete] = keyToMove;
// The next line is optional garbage collection.
// It increases the cost of this operation.
delete voterStructs[voterId];
voterList.length--;
return true;
}
}
This question is updated from the original post so the snippet works as intended. The gas figures are also updated.