0

Hey everyone

I'm using foundry for solidity development and I have some issues with using mappings and structs in my tests.

here are my problems:

Problem 1

the problem :

the function below lets users list their tokens for sale but when I want to test them, I get this error on assert(eProp.tokenIdToIsListed[0]) :

Indexed expression has to be a type, mapping or array (is function (uint256) view external returns (bool))

the function :

mapping(uint256 => bool) public tokenIdToIsListed;
mapping(uint256 => uint256) public tokenIdToPrice;

function listTokenForSale(
        uint256 tokenId,
        uint256 price
    ) public onlyTokenOwner(tokenId) {
        if (!_exists(tokenId)) {
            revert wrongTokenIdEnterd();
        }
        tokenIdToIsListed[tokenId] = true;
        tokenIdToPrice[tokenId] = price;
    }

the test :

function testListTokenForSale() public {
        eProp.mintProp(USER, 44, 65, 1, 1, 0);
        uint256 sellPrice = 1 ether;

        vm.prank(USER);
        eProp.listTokenForSale(0, sellPrice);

        vm.prank(USER);
        vm.expectRevert();
        eProp.listTokenForSale(2, sellPrice);

        assert(eProp.tokenIdToIsListed[0]);
        assert(eProp.tokenIdToPrice[0] == sellPrice);
    }

Problem 2

the problem :

the function below lets users make an offer and saves and pushes the offer in an array of offers in a private mapping. the other function lets the owner of tokens get the offers for their token.in this case, for testing these functions I need to get the offer object in my test.

I tried the library solution and made a library having my offer struct in it and then imported the library in my test file and it worked but in this case, I have to use the library for my whole contract and it feels not okay to me.

isn't there any other way to test my structs in Foundry?

the functions :

mapping(uint256 => Offer[]) private tokenIdToOffers;

function makeOffer(uint256 tokenId, uint256 offeredPrice) public {
        if (!_exists(tokenId) || ownerOf(tokenId) == msg.sender) {
            revert wrongTokenIdEnterd();
        }
        if (tokenIdToHighestBid[tokenId] != 0 || tokenIdToIsListed[tokenId]) {
            revert tokenAlreadyInSaleOrAuction();
        }
        Offer memory offer = Offer(msg.sender, offeredPrice);
        tokenIdToOffers[tokenId].push(offer);
    }

function getOffers(
        uint256 tokenId
    ) external view onlyTokenOwner(tokenId) returns (Offer[] memory) {
        return tokenIdToOffers[tokenId];
    }

the test :

 function testMakeOffer() public {
        
        eProp.mintProp(USER, 44, 65, 1, 1, 0);

        vm.prank(USER2);
        eProp.makeOffer(0, 1 ether);
        
        eProp.Offer[] memory offers = eProp.getOffers(0);

        assert(offers[0].sender == USER2);
        assert(offers[0].offerdAmount == 1 ether);
    }

1 Answer 1

0

Alright, I'll give you an answer to both problems which I hope will resolve your issues. :)

Problem 1:

The issue is that you expect the mapping to give back the results, like if you tried to get the given value of a key from a mapping in the same contract. However, as is suggested by the error, you're not receiving a mapping, since you made the mapping public, it should be treated as a function. So, what you need to do is the following:

assert(eProp.tokenIdToIsListed(0));
assert(eProp.tokenIdToPrice(0) == sellPrice);

Problem 2: I'm not sure if there are any other ways to do this, but you seem to be doing it right. But I've included an example of how to work with structs in Foundry right here:

    function setUp() external {
    cont = new MyContract();
  }

function testGetPersons() public {
    cont.addPerson(0, "Test", "TEST");
    cont.addPerson(0, "Test2", "TEST2");

    MyContract.Person[] memory persons = cont.getPersons(0);

    assertEq(persons.length, 2);
    assertEq(persons[0].name, "Test");
    assertEq(persons[0].symbol, "TEST");
    assertEq(persons[1].name, "Test2");
    assertEq(persons[1].symbol, "TEST2");
  }
5
  • Hey buddy, thanks for the answers. the first one worked but the second one didn't. I edited my second test, please take a look. it still says: "Identifier not found or not unique" on the struct definition.
    – emtothed
    Sep 28, 2023 at 13:42
  • I have another problem which I forgot to mention. when the code is getting compiled I get the error below for having too many variables. am I fine and should I just use "--via-ir" or there is something wrong and I should change the code?
    – emtothed
    Sep 28, 2023 at 13:46
  • the error : Compiler error (/solidity/libyul/backends/evm/AsmCodeGen.cpp:63):Stack too deep. Try compiling with --via-ir (cli) or the equivalent viaIR: true (standard JSON) while enabling the optimizer. Otherwise, try removing local variables. When compiling inline assembly: Variable pos is 3 slot(s) too deep inside the stack. Stack too deep. Try compiling with --via-ir (cli) or the equivalent viaIR: true (standard JSON) while enabling the optimizer. Otherwise, try removing local variables.
    – emtothed
    Sep 28, 2023 at 13:46
  • Hey there, I'm still passionately waiting for your help. thanks
    – emtothed
    Oct 2, 2023 at 9:28
  • I was using contact object instead of the imported contract itself. the problem got solved thanks
    – emtothed
    Oct 2, 2023 at 10:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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