[SOLVED] How do I access a smart contracts method that is **msg.sender** sensitive?

I successfully deployed a smart contract via the Remix Web3 Provider Environment.

My deployed contract has two public view methods of interest, namely the: viewAllGifts() method, and the viewMyGifts() methods.

The viewAllGifts() method (As you might have already guessed) returns an array of all the gifts unristricted by any modifier/msg.sender, while the viewMyGifts() method, restricts the user msg.sender to ONLY view gifts created by msg.sender them.

For clarity purposes, find below the relevant part of my contract code:

struct CryptoGift {
    address from;
    address to;
    uint256 tokenId;
    string  tokenName;
}

CryptoGift[] private allGifts;
mapping(address => CryptoGift[]) private myGifts;

function viewAllGifts() public view returns ( CryptoGift[] memory ) {
    return allGifts;   
}


function viewMyGifts() public view returns ( CryptoGift[] memory ) {       
    return myGifts[msg.sender];
}

In Remix I am naturally able to access the returns of the viewAllGifts() method regardless of the account I am in, however, for the viewMyGifts() method, I have to ensure that I am in account number: 0x1C94…91D0, which works perfectly as per design as I created all gifts while in account number: 0x1C94…91D0!

Via my HTML UI, I am also able to successfully view the returns of the viewAllGifts() method.

For clarity purposes, find below my Javascript code (in my HTML UI) calling my smart-contract viewAllGifts() method:

.
.
.
contractMethods.viewAllGifts().call( (error, result)=> {
   if(!error){   
      result.forEach((item, index)=>{
        console.log("Gift from: " +item.from);
        console.log("Gift from: " +item.to); 
        console.log("Gift from: " +item.tokeId);
        console.log("Gift from: " +item.tokenName);          })
    } else{
        console.log("Unauthorised access!");
    } 
})

The problem I have is that, via my HTML UI I am NOT able to access the viewMyGifts() method, Even if I change my account number in Metamask to 0x1C94…91D0.

Find below my Javascript code in the HTML UI, calling my smart-contract viewMyGifts() method:

.
.
.
contractMethods.viewMyGifts().call( (error, result)=> {
   if(!error){   
      result.forEach((item, index)=>{
        console.log("Gift from: " +item.from);
        console.log("Gift from: " +item.to); 
        console.log("Gift from: " +item.tokeId);
        console.log("Gift from: " +item.tokenName);          })
    } else{
        console.log("Unauthorised access!");
    } 
})

My assumption is that, somehow contractMethods.viewMyGifts().call doesn’t send my Metamask account number 0x1C94…91D0 when calling the viewMyGifts() method.

How do I access a smart contracts method that is msg.sender sensitive?

Find below further details regarding my smart contract:

In Remix, the Web3 Provider is Ganache

I imported the 0x1C94…91D0 account number from the many Ganache accounts into Metamask, and I am able to successfully interact with my smart contract method viewAllGifts() while using it, but NOT the viewMyGifts() method: my imported account in Metamask

Thanks

Can you add another method to that Smart contract that receives an address as parameter?

1 Like

Yes, I was able to add a method to the smart contract that receives my address as a parameter and I also wrote an equivalent javascript function that successfully captures my address (using the moralis API), sends it to the smart contract method and receives a response as well.

Find below my smart contract method code:

mapping(address => CryptoGift) public gifts;

function recieveAddress(address _giftersAddress) public view returns (string memory ) {
CryptoGift storage giftAddress = gifts[_giftersAddress];
require( giftAddress.from == _giftersAddress, “Unrecognised address!” );

  return "exists";
}

And following is my javascript code that interacts with the above smart contract recieveAddress() method:

const ethAddress = user.get(“ethAddress”);
contractMethods.recieveAddress(ethAddress).call( (error, result)=> {
if(!error){
alert("################## result: " +result);
} else{
alert("################## error: " +error);
}
});

This runs successfully. When I use the correct account via Metamask, I get an alert saying: “Exists”, otherwise a lengthy error message!

I STILL don’t understand how am supposed to run the:

viewMyGifts() method:

in the same contract

you may be able to run viewMyGifts() with send(), but it will cost gas fees

1 Like

Oh really?!
Even in the testnet environment?

Is there a way I can test my smart contract app gas-FREE?

.call is gas free .send is not gas free, in testnet or localdevchain it doesn’t really cost you something, but in testnet you need to get testnet native currency to test/deploy the contract

Hi cryptoKid!

I would like to thank you NOT for helping me resolve the issue, but for pointing me in the right direction leading me to resolve my issue on my own.

According to my research, my solidity function: viewMyGifts() being of a view mode, doesn’t alter any of the state variables in the blockchain, but merely reads the value of the state variables. Therefore using the .call is the recommended method to use and NOT the .send() method.

To recap, kindly find below my solidity viewMyGifts() function code, note the view:

function viewMyGifts() public view returns ( CryptoGift[] memory ) {
return myGifts[msg.sender];
}

Also find below the correct way to call the viewMyGifts() function via Web3, note that I attached a variable carrying my address and attached it to the from. This was the key element missing.

let ethAddress = user.get(“ethAddress”);

contractMethods.viewMyGifts().call( ({from: ethAddress}), (error, result)=> {
if(!error){
result.forEach((item, index)=>{
console.log("Gift from: " +item.from);
console.log("Gift from: " +item.to);
console.log("Gift from: " +item.tokeId);
console.log("Gift from: " +item.tokenName); })
} else{
console.log(“Unauthorised access!”);
}
})

I hope this also helps others struggling with similar problems.

1 Like