I can't seem to figure what is wrong with my function, the debugger keeps spawning flame spitting dragons on the 'priceOfItem' variable.

function purchaseItem(uint256 _itemID, uint256 _itemQuantity) public {
            require(_itemQuantity > 0);

            uint256 priceOfItem = itemData[uint256(_itemID)].unitPrice.mul(_itemQuantity);

            token.approve(contract, priceOfItem);
            token.transferFrom(msg.sender, wallet, priceOfItem);
            itemData[uint256(_itemID)].itemQuantity = itemData[uint256(_itemID)].itemQuantity.sub(_itemQuantity);
            emit ItemPurchased(msg.sender, _itemID, _itemQuantity, (priceOfItem));

The token.approve() has to be called by the token owner not by the contract.

In javascript it should be something like

token.approve(targetContract.address, priceOfItem,  { from: tokenOwner })
targetContract.purchaseItem(itemId, priceOfItem, { from: tokenOwner })

If the owner didn't call approve then token.transferFrom(msg.sender, wallet, priceOfItem) will generate a revert() because the contract is not allowed to transfer from token owner.

  • How can I charge ERC20 tokens from people calling the function? would using 'transfer' be enough? – NowsyMe May 2 '18 at 0:21
  • 1
    A smart contract cannot charge to an ERC20 token, you have to use the approve+transferFrom. With ERC223 you can somehow use the equivalent transfer+tokenFallback, your contract implement a tokenFallback function and when someone makes a transfer that function will be called. But in all the cases the user initiates the transfer. – Ismael May 2 '18 at 2:20
  • Thanks for clarifying, and it is not possible to do both approve+transferFrom from within the same function as I did above in solidity? token.approve doesn't seem to ever work for me if called from within the purchaseItem function, it only seems to work If I call it from tokenOwner directly from token contract which creates a sloppy flow. – NowsyMe May 2 '18 at 5:09
  • 1
    If your contract calls approve it is approving the target to use the contract's tokens. You want the contract to approve in behalf of the user but that is not possible, it is a security measure a contract cannot impersonate someone else. – Ismael May 2 '18 at 5:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.