41
struct buyer {
    uint amount;
    Status status;
}

mapping(address=>buyer) public buyers;
mapping(uint=>address) buyerIndex;
uint public buyerNum;

// Order a product.
function() {
    uint doubleValue=value*2;
    uint amount=msg.value/doubleValue;
    if(buyers[msg.sender]==null) { // Error in this line
        buyer abuyer=buyer({amount:amount,status:Status.Created}); // Error in this line
        buyerNum++;
        buyerIndex[buyerNum]=msg.sender;
        buyers[msg.sender]=abuyer;
    }
    else {
        buyers[msg.sender].amount+=amount;
    }
    Order(msg.sender,amount*doubleValue,amount);
}

If a buyer is not recorded in the buyer mapping, then buyerNum++; but I don't know how to tell whether a buyer is in the mapping

alper
  • 2,919
  • 9
  • 53
  • 102
Hao WU
  • 521
  • 1
  • 4
  • 5
  • 1
    Maybe like [How can I check if a variable or an array is set or empty or null](http://ethereum.stackexchange.com/a/2134/87), [Checking zero value of structure](http://ethereum.stackexchange.com/q/2502/87) or [What is the zero value for a string](http://ethereum.stackexchange.com/q/5683/87) at Ethereum Stack Exchange? – q9f Jun 17 '16 at 08:33

5 Answers5

22

In solidity every variable is set to 0 by default.

You should think of mappings as all possible combinations are set to 0 by default.

In your specific case I would use the following:

if (buyers[msg.sender].amount == 0)
Viktor Tabori
  • 2,087
  • 1
  • 13
  • 14
13

For integers:

You could create none variable to use it as a NULL:

uint256 constant NULL = 0;

Example code for check:

function isNULL(uint256 variable) internal returns (bool) {
    return variable == NULL;
}

For bytes32:

You can follow different approach for bytes:

bytes32 constant NULL = "";

Example code piece:

pragma solidity ^0.6.0;

mapping(address => bytes32) public Countries;   

function isCountriesInitialized(address _user) external view returns (bool) 
{
    if (Countries[_user] == NULL) // Returns true if `Countries[_user]` is not initialized
        return false;

    return true;
}

I observe that on solidity >= v0.6.0 it may return 32 for length even though it is not mapped.

Example of its returned value:

b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'

alper
  • 2,919
  • 9
  • 53
  • 102
5

As Viktor said, default value for all possible values in mapping is zero. So if a buyer has not already inserted in mapping, the amount value for that address will be zero. But this approach has a flaw, if a buyer does exists but its balance became zero after some operations, you will treat it as it does not exist.

I think the best approach is to add a exists member to the buyer struct with bool type. Default value for this member is false and when the buyer get created, you initialize it with true value. So you can check exactly if a buyer exist or not via this member.

Buyer struct:

struct buyer{
   uint amount;
   Status status;
   bool exists;
}

Initialize buyer:

buyer memory b = buyer(0, status, true);

Check if buyer exists:

if(buyers[msg.sender].exists) {
  //so can buy
}
4

There is nothing like null in solidity.

Just check for the length of the address:

if(buyers[msg.sender].length == 0){
    // do your thing
}

See also this answer on ethereum stack exchange.

Community
  • 1
  • 1
q9f
  • 11,293
  • 8
  • 57
  • 96
2

Instead of using one of the values or creating an extra boolean, you can check for the byte size of the structure.

if (bytes(buyers[msg.sender]).length > 0) {
    // buyer exists.
}
Arsen Khachaturyan
  • 7,904
  • 4
  • 42
  • 42
einaralex
  • 101
  • 9