I have a dapp where an admin can upload a number of cakes (20 to 30). People can come into the site and decide whether they want to buy a cake uploaded by admin.
So for smart contract, I made an array of uint to store each id of Cake whenever admin uploads. Once the buyer bought one of the cakes, it would delete that id of Cake in the array. I decided to delete it to avoid loops as much as possible since it would cause out of gas while I iterate the array to return the remaining list of cakes to buyers. How does it sound in terms of optimization?
Below is my implementation. Are there any better solutions or is this enough to continue?
struct Cake {
uint id;
address buyer;
}
mapping (uint => Cake) public cakes;
uint[] public cakeIds;
function addNewCake(uint _id) public {
cakes[_id] = Cake(_id, 0x0);
cakeIds.push(_id);
}
function buyCake(uint _id) public {
Cake storage cake = cakes[_id];
cake.buyer = msg.sender;
removeCakeInArray(_id);
}
function removeCakeInArray(uint _id) private {
for (uint i = 0; i <= getNumOfCakes(); i++) {
if (cakeIds[i] == _id) {
remove(i);
}
}
}
function remove(uint index) private {
if (index >= getNumOfCakes()) return;
for (uint i = index; i < getNumOfCakes() - 1; i++){
cakeIds[i] = cakeIds[i+1];
}
cakeIds.length--;
}
function getAllUnsoldCakes() public view returns (uint[]) {
uint length = getNumOfCakes();
uint[] memory ids = new uint[](length);
for (uint i = 0; i < length; i++) {
uint cakeId = cakeIds[i];
Cake memory cake = cakes[cakeId];
if (cake.buyer == 0x0) {
ids[i] = cake.id;
}
}
return ids;
}
function getNumOfCakes() public view returns (uint) {
return cakeIds.length;
}
remove()could be a red flag. What are the scenarios someone can increase an array on purpose? – bbusdriver Jun 17 '18 at 00:32addNewCake()is restricted to admin (which in your code it isn't) and they're completely trusted and the whole contract is broken anyhow their key is stolen then you're OK. If any of these things doesn't hold, a malicious user can just calladdNewCake()until the array is long enough that the loop inremove()uses more gas than the block gas limit. – Edmund Edgar Jun 17 '18 at 00:55