A few months back I posted this question on this form. Since then, I've used the interface method to make my smart contracts interact together. I didn't have any problem while testing and developing in Remix IDE using the JavaScript VM. I'm now building the front end and calling a function that interacts with a function from another smart contract generates an error.
The error is Unhandled Runtime Error Error: Transaction has been reverted by the EVM and the transaction fails with no revert messages.
I did notice that during compilation, there are two ABI's generated. One for the interface in the smart contract and one for the smart contract itself. I'm currently using the smart contract's generated ABI whilst not knowing how to use the interface ABI or whither I should use it.
To summarize: what should I do with the interface's ABI? Is not using it the reason behind the error.
This is how I made my two smart contracts interact:
The purpose is to get registered entities' details and use them in the modifier to check if they were pre-registered to the system.
pragma solidity ^0.5.0;
contract Register{
address public govermentEntity;
struct Seller {
address sellerAddress;
string sellerLocation;
string sellerName;
address [] sortingMachineAddress; // dynamic array
bool isExist;
}
constructor() public{
govermentEntity = msg.sender;
}
mapping (address => Seller) registeredSellers;
modifier onlyGovermentEntity{
require(msg.sender == govermentEntity, "Entity not authorized to register stakeholders.");
_;
}
function getSellerDetails(address addr) external view returns (address, string memory,string memory){
return(registeredSellers[addr].sellerAddress, registeredSellers[addr].sellerLocation,registeredSellers[addr].sellerName);
}
pragma solidity ^0.5.0;
interface RegisterSC{
function getSellerSortingmMachineDetails(address addr) external view returns ( address [] memory);
}
contract Tracking{
string public status;
address public caller;
modifier sortingMachineOnly (address registerContractAddr, address sellerAddr){
address[] memory tempArray;
RegisterSC registerSC = RegisterSC(registerContractAddr); //pass contract address
tempArray = registerSC.getSellerSortingmMachineDetails(sellerAddr); // pass address of sorting facility-seller
for(uint256 i=0; i< tempArray.length; i++){ //only registered sorting machines can update the status of the bottle
if (msg.sender == tempArray[i])
_;
}
}
function updateStatusSorted (address registerContractAddr, address sellerAddr, address plasticBottleAddress) public sortingMachineOnly (registerContractAddr, sellerAddr){
plasticBaleContributorsAddresses.push(bottleToRecycler[plasticBottleAddress]);
plasticBale.push(plasticBottleAddress);
bottlesSortedCounter++;
status = 'sorted';
}
This is how I'm calling the updateStatusSorted in the Dapp using web3: I'm keeping react details out of this segment to keep the question straight forward
import web3 from '../ethereum/web3';
import trackingContract from '../ethereum/tracking';
constructor() {
this.state = {
sellerAddress:'0x34....',
trackingSCAddress:'0xb.....'
}; }
sortBottle = async () => {
const accounts = await web3.eth.getAccounts();
await trackingContract.methods
.updateStatusSorted(this.state.trackingSCAddress,this.state.sellerAddress,this.state.result)
.send({ from: accounts[0] });
};
This is my tracking.js file:
import web3 from './web3';
import Tracking from './build/Tracking.json';
const instance = new web3.eth.Contract(
Tracking.abi,
'0xb......'
);
export default instance;
updateStatusSorted
. If you open the ABI file, you'll notice that it declares an array of objects. Each object is either a function prototype or an event prototype. The only object that you need is the one whosename
isupdateStatusSorted
. You can even declare an array containing that single object, and then pass that array when you create theweb3.eth.Contract
object. – goodvibration Jan 13 at 15:51