0

I have the following contract defined:

pragma solidity >=0.7.0 < 0.9.0;

contract LoanApplication {

     struct Applicant {
        bytes32 ssn;
    bool isTenant;
    
     }

     struct Loan {
        string loanID;
    uint applicantCount;
    uint256 rate;
    uint term;
      }

     mapping (address => Applicant) public applicants;

     Loan[] public loans;



     constructor(string[] memory loanIDs) {

       for (uint i=0; i < loanIDs.length; i++) {
            // Create Proposal object and append to proposals array
            loans.push(Loan({
                loanID: loanIDs[i],
                applicantCount:0,
        rate: 10,
        term: 30
                }));
        }
     
     }

}

I have written a Javascript test contract

const LoanAppContract = artifacts.require("LoanApplication");

contract("LoanApplicationTest", accounts => {


const loanIDs = ["Loan1", "Loan2", "Loan3"];

const banker = accounts[0];


beforeEach (async () =>  {
    loanApp = await LoanAppContract.new(loanIDs);
});
describe("initialization", () => {

it("gets the loan IDs", async () => {
    let loans = await loanApp.loans;

    //console.log("loan ID=" + loans[0].loanID); 1 - Unsuccessful

    let loanID = await loanApp.getLoanIDByIndex(0);

    console.log("loan ID=" + loanID);    // 2 - Succeeds

});



    it("Gets the applicants", async () => {
        let applicants = await loanApp.applicants;
        });

        });

});

Why can't I access the loans member array directly ? In order to make it work I have to define the following getter function in the contract:

 function  getLoanIDByIndex(uint index) external view returns (string memory){
       return loans[index].loanID;
    }

This line fails:

 //console.log("loan ID=" + loans[0].loanID); // 1 - Unsuccessful`

while this succeeds:

    let loanID = await loanApp.getLoanIDByIndex(0);

    console.log("loan ID=" + loanID);    // 2 - Succeeds```

Can someone explain why I need to create a getter ?

1 Answer 1

1

There is a getter automatically generated, but it is not the js array accessor.

If you look at the generated ABI you can see the folowing method:

        {
            "inputs": [
                {
                    "internalType": "uint256",
                    "name": "",
                    "type": "uint256"
                }
            ],
            "name": "loans",
            "outputs": [
                {
                    "internalType": "string",
                    "name": "loanID",
                    "type": "string"
                },
                {
                    "internalType": "uint256",
                    "name": "applicantCount",
                    "type": "uint256"
                },
                {
                    "internalType": "uint256",
                    "name": "rate",
                    "type": "uint256"
                },
                {
                    "internalType": "uint256",
                    "name": "term",
                    "type": "uint256"
                }
            ],
            "stateMutability": "view",
            "type": "function"
        }

This is automatically generated for public arrays. You can therefore load the information from the loans by doing:

const loan = await loanApp.loans(0);
console.log("loan ID=" + loan.loanID);
1
  • This is very helpful, thx...
    – femibyte
    Jan 5, 2022 at 11:25

Your Answer

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

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