Ethereum contract, running a function corrupts contract members - solidity

I made a simple contract that stores ether and then can send ether. The function that sends ether has a requirement that only the owner of the contract can send ether from the contract.
The contract mysteriously fails to send ether every subsequent call after the first.
I created a function to retrieve the owner address value in the contract and it turns out that after the first function call, it changes the data to 0x000000000000000000000000000000000000000a
Sending function:
function SendToAddress (uint8 amt, address adr) isOwner {
/* Have we transferred over the maximum amount in
the last 24 hours? */
if ((now - dayStartTime) >= secondsInADay) {
dayStartTime = now;
curDayTransfer = 0;
}
if ((curDayTransfer + amt) < dayMaxTransfer) {
adr.transfer (amt);
walletBalance -= amt;
curDayTransfer += amt;
MoneyTransfer newTransfer;
newTransfer.amount = amt;
newTransfer.target = adr;
newTransfer.timeStamp = now;
if (transferHistory.length == 100) {
// Shift all of the transactions in the history list forward
// to make space for the transaction.
for (uint8 i = 1; i < 100; i++) {
transferHistory[i] = transferHistory[i-1];
}
transferHistory[0] = newTransfer;
} else {
transferHistory.push (newTransfer);
}
}
}
isOwner modifier:
modifier isOwner() {
require(msg.sender == creatorAddress);
_;
}
constructor:
constructor () public {
creatorAddress = msg.sender;
}

I assume the compiler gives you a warning on the line MoneyTransfer newTransfer; about implicitly storing the data in storage. If you explicitly use MoneyTransfer storage newTransfer;, then you'll get a warning that you're using an uninitialized storage reference. That means whatever values you put in newTransfer will overwrite whatever's in the first few storage slots.
Use MoneyTransfer memory newTransfer; instead.

Related

ERC721A smart contract

I'm writing an ERC721A smart contract and getting a warning in the Remix IDE. There is the code:
function tokenOfOwnerByIndex(address owner, uint256 index) public view override returns (uint256) {
if (index >= balanceOf(owner)) revert OwnerIndexOutOfBounds();
uint256 numMintedSoFar = totalSupply();
uint256 tokenIdsIdx;
address currOwnershipAddr;
// Counter overflow is impossible as the loop breaks when uint256 i is equal to another uint256 numMintedSoFar.
unchecked {
for (uint256 i; i < numMintedSoFar; i++) {
TokenOwnership memory ownership = _ownerships[i];
if (ownership.addr != address(0)) {
currOwnershipAddr = ownership.addr;
}
if (currOwnershipAddr == owner) {
if (tokenIdsIdx == index) {
return i;
}
tokenIdsIdx++;
}
}
}
// Execution should never reach this point.
assert(false);
}
This code is from the Square Bears collection ( https://etherscan.io/address/0x2b1037def2aa4ed427627903bdef9bdd27ae1ea3#code ). I got it from a YouTube tutorial. I think the code works, but I keep getting a warning.
Warning: Unnamed return variable can remain unassigned. Add an explicit return with value to all non-reverting code paths or name the variable.
--> contracts/ERC721A.sol:103:94:
|
103 | function tokenOfOwnerByIndex(address owner, uint256 index) public view override returns (uint256) {
| ^^^^^^^
I assume that I have to provide a named return value or variable, but the code seems to return an iterated value (i).
Because you've told the compiler that you will return a value from the function, but you didn't.
You should return a mock value even if you don't need to.
...
// Execution should never reach this point.
assert(false);
return tokenIdsIdx; // or simply return 0;
}

How to store unique value in an array using for loop in Solidity?

I want to store unique addresses in the array and then increment the count. But I am not able to do it. The count variable is not incremented and returns 0. Also redundant addresses are stored in the array.
Can you please help?
function placeBid() public payable notOwner afterStart beforeEnd returns(bool){
require(auctionState == State.Running);
uint currentBid = 0;
if(totalBidder>0)
{
currentBid = bids[msg.sender] + msg.value;
require(currentBid > highestBindingBid);
}
else{
require(msg.value > startBid && msg.value > highestBindingBid);
currentBid = msg.value;
}
bids[msg.sender] = currentBid;
for(uint i=0; i<bidders.length; i++){
if(msg.sender!=bidders[i])
bidders.push(payable(msg.sender));
totalBidder++;
}
}
highestBindingBid = currentBid;
highestBidder = payable(msg.sender);
return true;
}
An easy (and cheaper compared to your snippet) way to push only unique items to a storage array is to duplicate the values in a mapping, and then validate against the mapping.
pragma solidity ^0.8;
contract MyContract {
address payable[] public bidders;
mapping (address => bool) isBidder; // default `false`
// only add `msg.sender` to `bidders` if it's not there yet
function placeBid() public {
// check against the mapping
if (isBidder[msg.sender] == false) {
// push the unique item to the array
bidders.push(payable(msg.sender));
// don't forget to set the mapping value as well
isBidder[msg.sender] = true;
}
}
}

how to add function for closing and opening bet per match smart contract?

source code:https://github.com/laronlineworld/bettingMatch/blob/main/bettingMatch.sol
How to open and close bet per match
function bet(uint16 _matchSelected, uint16 _resultSelected) public payable {
//Check if the player already exist
// require(!checkIfPlayerExists(msg.sender));
//Check if the value sended by the player is higher than the min value
require(msg.value >= minimumBet);
//Set the player informations : amount of the bet, match and result selected
playerInfo[msg.sender].amountBet = msg.value;
playerInfo[msg.sender].matchSelected = _matchSelected;
playerInfo[msg.sender].resultSelected = _resultSelected;
//Add the address of the player to the players array
players.push(msg.sender);
//Finally increment the stakes of the team selected with the player bet
if ( _resultSelected == 1){
totalBetHome[_matchSelected] += msg.value;
}
else if( _resultSelected == 2){
totalBetAway[_matchSelected] += msg.value;
}
else{
totalBetDraw[_matchSelected] += msg.value;
}
}
This is the code for opening the betting
/* Function to enable betting */
function beginVotingPeriod() public onlyOwner returns(bool) {
bettingActive = true;
return true;
}
how about opening the bet per match?
also closing the bet per match
/* Function to close voting and handle payout. Can only be called by the owner. */
function closeVoting() public onlyOwner returns (bool) {
// Close the betting period
bettingActive = false;
return true;
}
The linked code recognizes a match as index of these arrays: totalBetHome, totalBetAway and totalBetDraw.
You can add a mapping where the key is the match ID, and the value is a flag signalizing whether there's a betting enabled on the match or not.
// default value for each is `false`
mapping (uint256 => bool) isMatchEnabled;
function enableBetting(uint256 _matchId) external onlyOwner {
isBettingEnabled[_matchId] = true;
}
function disableBetting(uint256 _matchId) external onlyOwner {
isBettingEnabled[_matchId] = false;
}
Then you can amend the bet() function - add a condition requiring betting for this match to be enabled.
function bet(uint16 _matchSelected, uint16 _resultSelected) public payable {
require(isBettingEnabled[_matchSelected] == true);
// rest of your code
}
Note: Solidity v0.4.2 that you're using in the linked code, is few years old and has few security issues. The current version (August 2021) is 0.8.7. Consider upgrading to the latest version.

Solidity variable definition: (bool sent, )

In Solidity, this sentence:
(bool sent, ) = msg.sender.call{value: _amount}("");
What is the sense of that "," after sent variable?
Any link to offcial documentation?
Many thanks.
It means you do not need to define both the variables to access the return values. You can access either of these variables as follows
(,uint256 alpha) = testFunction(); //access first returned variable
(uint256 beta,) = testFunction(); //access second returned variable
function testFunction() public pure returns(uint256,uint256){
return (1,2);
}
Solidity functions can return multiple variables of different types.
If you only want to keep one variable, then you can declare a variable and then use commas:
function multiValueFunction() public returns (bool, string memory, uint[] memory, uint {
//do something
return (true, "New String", [1,2], 21)
}
function differentFunction() public {
uint numberToKeep;
(,,,numberToKeep) = multiValueFunction();
}
Expected: numberToKeep = 21
Each comma represents the place of a returned variable (that is not kept)
It just means that the function will return two variables and you just want to store the first one.
This kind of syntax (variable type) is called Tuple In Python and other languages.
In Solidity,
they're not considered a proper type but can be used as a shorthand.
See the Official Docs: Destructuring Assignments and Returning Multiple Values
example:
uint256 amount = 10 ether;
require(
amount <= address(this).balance,
"Trying to withdraw more money than the contract has."
);
(bool success, ) = (msg.sender).call{value: amount}("");
require(success, "Failed to withdraw money from contract.");
above code, Roughly, Can be translated with basic if else statements like following:
uint256 amount = 10 ether;
bool success;
if(amount <= address(this).balance) {
success = true;
} else {
success = false;
return "Trying to withdraw more money than the contract has.";
}
if(success) {
(msg.sender).call{value: amount}("")
} else {
return "Failed to withdraw money from contract.";
}
here's another contract as example,
use this link https://remix.ethereum.org/#version=soljson-v0.6.9+commit.3e3065ac.js&optimize=false&gist=83bfbd85ef79387f760154999eb4f192&runs=200&evmVersion=null to play around in remix online
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.5.0 <0.8.0;
contract myContract {
uint index;
function myFunction() public {
( , , uint256 standardDepositAmount, , ) = returnTuple();
require(standardDepositAmount == 3);
// do something...
}
function returnTuple() public pure returns (uint, uint, uint, uint, uint) {
return (1, 2, 3, 4, 5);
}
}

If statement in for loop not filtering out items in solidity

// #param physicalAddress - the actual address of the home a host wants to list (not the ethereum address)
// #return _id - list of ids for homes
function listHomesByAddress(string _physicalAddress) public returns(uint [] _id ) {
uint [] results;
for(uint i = 0 ; i<homes.length; i++) {
if(keccak256(homes[i].physicalAddress) == keccak256(_physicalAddress) && homes[i].available == true) {
results.push(homes[i].id);
}
}
return results;
}
The result is supposed to be a list of ids which match the physical address entered however it does not filter through but returns all the available homes.
When I change to using String utils nothing changes.
Here is the whole code:
pragma solidity ^0.4.0;
import "browser/StringUtils.sol";
// #title HomeListing
contract HomeListing {
struct Home {
uint id;
string physicalAddress;
bool available;
}
Home[] public homes;
mapping (address => Home) hostToHome;
event HomeEvent(uint _id);
event Test(uint length);
constructor() {
}
// #param physicalAddress - the actual address of the home a host wants to list (not the ethereum address)
function addHome(string _physicalAddress) public {
uint _id = uint(keccak256(_physicalAddress, msg.sender));
homes.push(Home(_id, _physicalAddress, true));
}
// #param physicalAddress - the actual address of the home a host wants to list (not the ethereum address)
// #return _id - list of ids for homes
function listHomesByAddress(string _physicalAddress) public returns(uint [] _id ) {
uint [] results;
for(uint i = 0 ; i<homes.length; i++) {
string location = homes[i].physicalAddress;
if(StringUtils.equal(location,_physicalAddress )) {
results.push(homes[i].id);
}
}
return results;
}
}
The part giving you trouble is the line uint[] results;. Arrays declared as local variables reference storage memory by default. From the "What is the memory keyword" section of the Solidity docs:
There are defaults for the storage location depending on which type of variable it concerns:
state variables are always in storage
function arguments are in memory by default
local variables of struct, array or mapping type reference storage by default
local variables of value type (i.e. neither array, nor struct nor mapping) are stored in the stack
The result is you're referencing the first storage slot of your contract, which happens to be Home[] public homes. That's why you're getting the entire array back.
To fix the problem, you need to use a memory array. However, you have an additional problem in that you can't use dynamic memory arrays in Solidity. A workaround is to decide on a result size limit and declare your array statically.
Example (limited to 10 results):
function listHomesByAddress(string _physicalAddress) public view returns(uint[10]) {
uint [10] memory results;
uint j = 0;
for(uint i = 0 ; i<homes.length && j < 10; i++) {
if(keccak256(homes[i].physicalAddress) == keccak256(_physicalAddress) && homes[i].available == true) {
results[j++] = homes[i].id;
}
}
return results;
}