1

I'm following the Ethereum Pet Shop tutorial online, and everything works fine. However, to "adopt" a pet, the MetaMask transaction on my site is only requiring me to pay for the gas. I've taken a look at the Solidity docs and I think I'm supposed to make my function "payable", which I've tried, but actually setting a required price in wei to execute the contract is unclear to me.

Here's my Adoption.sol file:

pragma solidity ^0.4.17;

contract Adoption {
    address[16] public adopters;
    // Adopting a pet
    function adopt(uint petId) public payable returns (uint) {
        require(petId >= 0 && petId <= 15);

        adopters[petId] = msg.sender;

        return petId;
    }
    // Retrieving the adopters
    function getAdopters() public view returns (address[16]) {
        return adopters;
    }

}

And my TestAdoption.sol file:

pragma solidity ^0.4.17;

import "truffle/Assert.sol";
import "truffle/DeployedAddresses.sol";
import "../contracts/Adoption.sol";

contract TestAdoption {
    Adoption adoption = Adoption(DeployedAddresses.Adoption());

    //Testing the adopt() function
    function testUserCanAdoptPet() public {
      uint returnedId = adoption.adopt(8);
      uint expected = 8;
      Assert.equal(returnedId, expected, "Adoption of pet ID 8 should be recorded.");
    }

    // Testing retrieval of a single pet's owner
    function testGetAdopterAddressByPetId() public {
        // Expected owner is this contract
        address expected = this;
        address adopter = adoption.adopters(8);
        Assert.equal(adopter, expected, "Owner of pet ID 8 should be recorded.");
    }

    // Testing retrieval of all pet owners
    function testGetAdopterAddressByPetIdInArray() public {
        // Expected owner is this contract
        address expected = this;

        // Store adopters in memory rather than contract's storage
        address[16] memory adopters = adoption.getAdopters();

        Assert.equal(adopters[8], expected, "Owner of pet ID 8 should be recorded.");
    }

}

Can anyone point me in the right direction?

1

The MetaMask transaction prompt is opened by your JavaScript code not your Solidity code. If you want it to include a default value you will have to add that value in your JavaScript, by adding it as a value parameter to your call to adopt().

To enforce payment as a requirement for adoption, you will also need to add some code to your Solidity adopt() function to check msg.value and throw an error if it's lower than however much it's supposed to be. You may also want to add a read-only constant function to tell the user how much they have to pay, then call that from your JavaScript code to fetch the value that you will then set as the default that will be displayed by MetaMask.

| improve this answer | |
  • So my call to adopt() looks like this now: return adoptionInstance.adopt(petId, value="1000", {from: account});, but when I try to click on "Adopt" on the page, I get an error in the console saying "Invalid number of arguments to Solidity function". Do I have to update function adopt(uint petId) to something like function adopt(uint petId, uint value) or something like that? Thanks for the help by the way. – rustyshackleford Feb 15 '18 at 0:24
  • Try return adoptionInstance.adopt(petId, {from: account, value: 1000}). Also note that the 1000 is in Wei, 1000 of which will be a very small number of ETH. I think MetaMask might end up rounding that down to 0, in which case you might like to try a grander number. – Edmund Edgar Feb 15 '18 at 4:44
1

Yes, you need to add payable, as it looks like you did. Then you just need to check that the right amount of ether was sent. E.g.:

require(msg.value == priceInWei);

If you want adopting a pet to cost 1 ether, then you can do:

require(msg.value == 1 ether);

Note that you'll also have to change your tests to send ether along. E.g.:

adoption.adopt.value(1 ether)(8);
| improve this answer | |
  • 1
    and how about the JavaScript that Edmund mentioned? I'm trying to pass a value to adopt() but the MetaMask UI now shows all of the values to be 0. – rustyshackleford Feb 15 '18 at 1:27
  • I don't use Truffle myself, but I believe it should be adoptionInstance.adopt(petId, { value: 1000, from: account }); (Replace 1000 with whatever price you're requiring. E.g. web3.toWei(1, 'ether').) – user19510 Feb 15 '18 at 1:50

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.