4

I need to access books array of Student contract in ClassRoom contract.

If i write as function readStudentStruct (uint ID) constant returns (address, uint, bool,address[]) then error

Different number of arguments in return statement than in returns declaration.
        return student.StudentNames(ID);

or if written without address[] then works fine.

pragma solidity ^0.4.0;
contract Student{

    struct stu{
        address name;
        uint age;
        bool tookTest;
        address[] books;
    }

    stu public s;

    mapping(uint => stu) public StudentNames;

    function addStudent (uint ID, address _name, uint _age,address[] books) {
        StudentNames[ID] = stu(_name, _age, false, books);
    }
    function updateStudent (uint ID) {
        StudentNames[ID].tookTest = true;
    }

    function getBooks(uint ID) returns(address[]){
        return StudentNames[ID].books;
    }

}
contract ClassRoom {
    address studentAddr;

    Student student;

    function ClassRoom(address addr) {
        studentAddr = addr;
        student = Student(addr);
    }
    function updateTookTest (uint ID) {
        student.updateStudent(ID);
    }

    //working fine
    function readStudentStruct (uint ID) constant returns (address, uint, bool) {
        return student.StudentNames(ID);
    }

   //showing error
   function readStudentStruct (uint ID) constant returns (address, uint, bool,address[]) {
        return student.StudentNames(ID);
    }
}

as per struct with address array function should worked but didn't.

why books array not coming in parent contract? or any way to get books array in parent contract?

Rob Hitchens
  • 55,151
  • 11
  • 89
  • 145
comeback4you
  • 302
  • 1
  • 3
  • 11

1 Answers1

2

Main issue is we can't pass a dynamic array[] in/out of the function. We have to break it down into a fixed-sized interface.

Here's a sketch following a simple pattern with 4 entities tracked and some relationships.

  1. Class
  2. Student
  3. Books
  4. and a many-to-many for class-students

The pattern isn't complicated but working with 4 entities at a time and the joins makes for a tough introduction.

Have a look here for more illustrative code: Are there well-solved and simple storage patterns for Solidity?

You'll probably want to support a logical delete so a student can return their books. I've skipped it because it calls for a trickier pattern.

No testing. No warranty. Hopefully provides some ideas.

pragma solidity ^0.4.0;

contract School {

    struct ClassStruct {
        bytes32 title;
        bytes32 teacher;
        mapping(address => ClassStudentStruct) classStudentStructs;
        address[] studentList;
        bool isClass;
    }

    mapping(bytes32 => ClassStruct) public classStructs; // access by Id
    bytes32[] public classList; // enumerate the keys to the mapping

    struct StudentStruct {
        bytes32 name;
        bytes32[] bookList; // student has books
        mapping(bytes32 => bool) isStudentBook;
        bool isStudent;
    }

    mapping(address => StudentStruct) public studentStructs;
    address[] public studentList;

    struct BookStruct {
        bytes32 title;
        bytes32 author;
        bool isBook;
    }

    mapping(bytes32 => BookStruct) public bookStructs;
    bytes32[] public bookList;

    // many-to-many

    struct ClassStudentStruct {
        address student;
        bool tookTest;
        bool isClassStudent;
    }

    function getClassCount()   public constant returns(uint count) { return classList.length; }
    function getStudentCount() public constant returns(uint count) { return studentList.length; }
    function getBookCount()    public constant returns(uint count) { return bookList.length; }

    function newClass(bytes32 classId, bytes32 title, bytes32 teacher) returns(bool success) {
        if(classStructs[classId].isClass) throw; // duplicate key
        classStructs[classId].title = title;
        classStructs[classId].teacher = teacher;
        classStructs[classId].isClass = true;
        classList.push(classId);
        return true;
    }

    function newStudent(address studentAddress, bytes32 name) returns(bool success) {
        if(studentStructs[studentAddress].isStudent) throw;
        studentStructs[studentAddress].name = name;
        studentList.push(studentAddress);
        studentStructs[studentAddress].isStudent = true;
        studentList.push(studentAddress);
        return true;
    }

    function newBook(bytes32 bookId, bytes32 title, bytes32 author) returns(bool success) {
        if(bookStructs[bookId].isBook) throw;
        bookStructs[bookId].title = title;
        bookStructs[bookId].author = author;
        bookStructs[bookId].isBook = true;
        bookList.push(bookId);
        return true;
    }

    function addClassStuduent(bytes32 classId, address studentAddress) returns(bool success) {
        if(!studentStructs[studentAddress].isStudent) throw; // not a student
        if(!classStructs[classId].isClass) throw; // not a class
        if(classStructs[classId].classStudentStructs[studentAddress].isClassStudent) throw; // student already enrolled in this class

        ClassStudentStruct memory newStudent;
        newStudent.student = studentAddress;
        newStudent.isClassStudent = true;
        classStructs[classId].studentList.push(studentAddress);
        return true;
    }

    function addStudentBook(bytes32 bookId, address studentAddress) returns(bool success) {
        if(!bookStructs[bookId].isBook) throw;
        if(!studentStructs[studentAddress].isStudent) throw;
        if(studentStructs[studentAddress].isStudentBook[bookId]) throw;

        studentStructs[studentAddress].isStudentBook[bookId] = true;
        studentStructs[studentAddress].bookList.push(bookId);
        return true;
    }


    // logical deletes need a more intricate pattern - Last one here:
    // https://ethereum.stackexchange.com/questions/13167/are-there-well-solved-and-simple-storage-patterns-for-solidity 

    function delStudentBook(bytes32 bookId, address studentAddress) returns(bool success) {}
    function delClassStudent(bytes32 classId, address studentAddress) returns(bool success) {}

}

Hope it helps.

Rob Hitchens
  • 55,151
  • 11
  • 89
  • 145