简体   繁体   中英

Solidity: "The called function should be payable if you send value and the value you send should be less than your current balance"

Im new to Solidity, I got a problem that when I call purchaseCard function, it always returns the error The called function should be payable if you send value and the value you send should be less than your current balance. on Remix IDE.

I think the problem is at the complexity of my structs or I probably called variables not allowed. But I still cant find fix after many days researching.


These are my structs.

struct Card {
    string name;
    uint price;
}
mapping(uint => Card) public cards;
uint public numberOfTypes;

struct Purchase {
    Card card;
    uint purchaseDate;
}

struct User {
    uint numberOfCards;
    Purchase[] purchase;
    bool exist;
}
mapping(address => User) public users;

And these are my functions, I will make it short.

// function addCard(string memory _name, uint _price) public isOwner;
// function removeCard(uint _id) public isOwner;
// function checkExistedUser(address _userAddress) public view returns(bool);

function purchaseCard(uint _id) public {
    User storage user = users[msg.sender];
    if (!checkExistedUser(msg.sender)) {
        user.exist = true;
        user.numberOfCards = 0;
    }
    Purchase storage purchase = user.purchase[user.numberOfCards];
    purchase.card = cards[_id];
    purchase.purchaseDate = block.timestamp;
    user.numberOfCards++;
}

// function expiredCard(uint _id) public;
// function showRemainingDate(uint _id) public view returns(uint);
// function showPurchasedCards() public view returns (Purchase[] memory);

This is my full code: https://github.com/SnowyField1906/code/blob/main/purchase.sol

Thank you very much, I hope to learn more things.

In this case, you cannot create an empty 'space' for purchase array in storage before fill it because the type of this operation is an array and not a mapping!

To solve this issue, you can use the push() method (available only for storage array) to fill purchase() array into Purchase struct.

Following your logic, you must change purchaseCard() method in this way:

function purchaseCard(uint _id) public {
   User storage user = users[msg.sender];
   if (!checkExistedUser(msg.sender)) {
     user.exist = true;
     user.numberOfCards = 0;
   }
   user.purchase.push(Purchase(cards[_id], block.timestamp));
   user.numberOfCards++;
}

In Solidity, If you have to send/receive ETHs then the payable function should be used. Try this:

function purchaseCard(uint _id) public payable {

or add payable to your constructor.

pls refer to this: https://solidity-by-example.org/payable/

And btw pls next time share the complete code snippet.

I can't able to understand the entire code and flow.. but while debugging..

the revert occurs in the belowline of the purchasecard function

 Purchase storage purchase = user.purchase[user.numberOfCards];

It seems like you are accessing the user mapping which does not contain any User Struct..

I think you forgot to assing the value to the user mapping in the addCard Function.

I may be wrong and I hope it helps..

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM