1

The second contract needs to check the mapping in the first contract to see if the person finished the required course. I checked a few old threads but they said it wasn't possibly with that version of solidity. Is there currently any simple way to do it?

Error: TypeError: Indexed expression has to be a type, mapping or array (is function (uint256) view external returns (enum Training.courses))

// SPDX-License-Identifier: MIT
pragma solidity 0.8.7;

contract Training{

enum  courses {course_1, course_2, course_3}

struct TrainedPerson{
    courses courseNo;
    }

 mapping (uint256 => TrainedPerson) public personnelList;

 function train(uint256 _ID, courses _courseNo) public {
 personnelList[_ID] =  TrainedPerson( _courseNo);
    }
}

contract Assigning{

 address addr;

    function setAddress(address _addr) external{
        addr = _addr;
    }

     Training A = Training(addr);

function assign(uint256 _ID, Training.courses _courseNo) public{
  require (A.personnelList[_ID].courseNo == Training.courses.course_3); //ERROR
}
}

3 Answers 3

1

In the latest version of Solidity, for calling getter() function about public variable you must use round brackets [()]. In your case you must use this statement:

contractName.mappingName('parameterForQuerying');

In your smart contract, for retrieve the only enum field you must change this line:

require (A.personnelList(_ID).courseNo == Training.courses.course_3);

into:

require (A.personnelList(_ID) == Training.courses.course_3);

You can read more here.

There isn another error in your code. In details, when you wrote this: Training A = Training(addr);

There isn't another error in your code. In details, when you wrote this: Training A = Training(addr);

and deploy for the first time the smart contract the default value about address type is 0x and because 'A' variable it is a storage variable the value stored inside it will be the address default regardless if and when you will call setAddress() function. A solution to this issue is to pass the Training smart contract address deployed already in the constructor of Assigning.

This is an entire example of how to do it including the fixes about TypeError:

// SPDX-License-Identifier: MIT
pragma solidity 0.8.7;

contract Training {
    enum courses {course_1, course_2, course_3}

    struct TrainedPerson{
        courses courseNo;
    }

    mapping (uint256 => TrainedPerson) public personnelList;

    function train(uint256 _ID, courses _courseNo) public {
        personnelList[_ID] =  TrainedPerson(_courseNo);
    }
}

contract Assigning{
    Training A;

    constructor(address addr) {
        A = Training(addr);
    }
    
    function assign(uint256 _ID, Training.courses _courseNo) public {
        require (A.personnelList(_ID) == Training.courses.course_3, "Generic error");
    }
}
1

mapping (uint256 => TrainedPerson) public personnelList;

Because the variable personnelList is declared as public, there will be a personnelList(uint256) get function. The return value of this function is a tuple.

In your example,(courses courseNo) = A.personnelList(_ID);.If struct TrainedPerson is

struct TrainedPerson {
    courses courseNo;
    uint256 score;
}

personnelList return value :(courses courseNo, uint256 score) = A.personnelList(_ID);

// SPDX-License-Identifier: MIT
pragma solidity 0.8.7;

contract Training {
    enum courses {
        course_1,
        course_2,
        course_3
    }

    struct TrainedPerson {
        courses courseNo;
    }

    mapping(uint256 => TrainedPerson) public personnelList;

    function train(uint256 _ID, courses _courseNo) public {
        personnelList[_ID] = TrainedPerson(_courseNo);
    }
}

contract Assigning {
    Training A;

    function setAddress(address _addr) external {
        A = Training(_addr);
    }

    function assign(uint256 _ID, Training.courses _courseNo) public view {
        (Training.courses courseNo) = A.personnelList(_ID);
        require(courseNo == _courseNo);
    }
}
1

First, you cannot directly read a variable from another contract, even if it's public. You need to use the public getter personnelList(), and in this case, wrap it in the struct to be able to read it's properties. Also, you need to initialize the address in setAddress(), otherwise it will be zero.

contract Assigning {
    address addr;
    Training A;

    function setAddress(address _addr) external {
        addr = _addr;
        A = Training(addr);
    }

    function assign(uint256 _ID, Training.courses _courseNo) public view {
        require (Training.TrainedPerson(A.personnelList(_ID)).courseNo == Training.courses.course_3, "Generic error");
    }
}

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.