1

I am new to Solidity and tried to write a contract. Now for better developing reasons I made myself a setup with truffle. Previously I used to work with remix only. My Project contains multiple contracts. In remix I used to deploy the first contract and then insert it's address into the other contracts. There I used for each Contract abstractions. Now I tried to integrate one contract and it's avstract zo my truffle environment. But it doesn't seem to work as expected. Disregarding the quality of the code itself, truffle won't deploy my contract (see the output below).

I looked around different posts like (https://www.toshblocks.com/solidity/abstract-contracts-solidity/ or Deploying abstract contracts and interfaces). But it seems like I can't find the solution to this problem/misunderstanding myself.

See the following files

The Abstraction (.abstracts/organAbstract.sol):

pragma solidity 0.4.24;

// Contract declaration
contract organA {

// Structs
struct organ { address originOwner; address currentOwner; string organType; string organState; }

// Signatures for all functions within the organ contract
function addOrgan(address _originOwner, string _type, string _state) external returns(bytes32 organHash);
function changeOrganState(bytes32 _organId, string _state) public;
function getOrganListLength() public view returns(uint ListLenght);
function getOrganList(uint indexNumber) public view returns(bytes32 OrganId);
function getOrgan(bytes32 _organHash) public view returns(address OriginOwner, address CurrentOwner, string OrganType, string OrganState);
function existsOrgan(bytes32 _organHash) external view returns(bool Existence);
function organOriginOwner(bytes32 _organHash) external view returns(address OriginOwner);
}

The Contract (./contracts/organ.sol):

pragma solidity 0.4.24;

// Import Abstracts
import "../abstracts/organAbstract.sol";

contract organContract is organA {

// --- Global variables --- //
address contractOwner;
uint256 organCount;

// Constructor for contract entity_organs
constructor() public {
    contractOwner = msg.sender; // Declare first sender as owner
    emit stateOwner(msg.sender); // Trigger event
    organCount = 0; // Set the counter to 0
}

// Mapping for Organs
mapping (bytes32 => organ) private organsList;
mapping (uint256 => bytes32) private organIndex;

// Organs Array
bytes32[] private organsListByHash;

// --- Modifiers --- //

// Modifier to allow contract owner only
modifier contractOwnerOnly () {
    // Require the given address to be the same
    require(msg.sender == contractOwner, "You are not allowed to interact!");
    _;
}

// Check if the organ exists
modifier checkOrganExistence(bytes32 _organHash) {
    require(bytes(organsList[_organHash].organState).length != 0, "Organ with given id doesn't exist!");
    _;
}

// Require atleast one organ on count
modifier organCountMin() {
    require(organCount != 0, "No organs found to return!");
    _;
}

// --- Events --- //

// Event when first transaction gets owner
event stateOwner (
    address ownerAddress
);

// Event when a new organ gets added
event newOrganAdded (
    address organOwner,
    bytes32 organId
);

// Event when organ state has changed
event organStateChanged (
    bytes32 organId,
    string state
);


// -- Organ Functions -- //

// Function to add a new organ to an owner
// This function will be called over the entityContract
function addOrgan(address _originOwner, string _type, string _state) external returns(bytes32 organHash) {

    // Somehow unique (There is no raqndom generator available)
    bytes32 uniqueOrgan = keccak256(_type, _originOwner);

    // Pass the values
    organsList[uniqueOrgan].originOwner = _originOwner; // insert the owner
    organsList[uniqueOrgan].currentOwner = _originOwner; // insert the owner
    organsList[uniqueOrgan].organType = _type; // insert the organ type
    organsList[uniqueOrgan].organState = _state; // Insert the organ state

    // Update the index
    organIndex[organCount] = uniqueOrgan; // Enter the hash for the integer key
    organCount++; // Update the global counter

    organsListByHash.push(uniqueOrgan); // Push to Array
    emit newOrganAdded(_originOwner, uniqueOrgan); // Trigger event

    // Return Organ for
    return uniqueOrgan;
}

// Change organ state (in prototype only type)
function changeOrganState(bytes32 _organId, string _state) checkOrganExistence(_organId) public {
    // Blacklist certain states if donator still alive
    // DATE COMPARISON https://github.com/pipermerriam/ethereum-datetime

    organsList[_organId].organState = _state; // Change organ state
    emit organStateChanged(_organId, _state);
    return;
}

// Function to view to length of organs
// Returns the value as integer of the array length
function getOrganListLength() organCountMin() public view returns(uint ListLenght) {
    return organCount;
}

// Function to return the entire list for organs
function getOrganList(uint indexNumber) organCountMin() public view returns(bytes32 OrganId) {
    return organIndex[indexNumber]; // Return the array
}

// Function to show organ with properties
// With the given id to web3js foreach organ can be viewd it's properties by id
function getOrgan(bytes32 _organHash) checkOrganExistence(_organHash) public view returns(address OriginOwner, address CurrentOwner, string OrganType, string OrganState) {
    // Return the value
    return (
        organsList[_organHash].originOwner,
        organsList[_organHash].currentOwner,
        organsList[_organHash].organType,
        organsList[_organHash].organState
    );
}

// Function to return organs existence (for external contracts)
function existsOrgan(bytes32 _organHash) external view returns(bool Existence) {
    if (bytes(organsList[_organHash].organState).length != 0) { return true; } else { return false; }
}

// Function to return origin owner of an organ
function organOriginOwner(bytes32 _organHash) organCountMin() checkOrganExistence(_organHash) external view returns(address OriginOwner) {
    return organsList[_organHash].originOwner;
}
}

This is the Deployment definition:

var organC = artifacts.require("./organ.sol");

module.exports = function(deployer) {
    deployer.deploy(organC, {overwrite: true})
};

After running the following command:

sudo truffle deploy --reset

I get this output:

 2_deploy_contracts.js
 =====================
 Error:  *** Deployment Failed ***

 "organ" is an abstract contract or an interface and cannot be deployed.
 * Import abstractions into the '.sol' file that uses them instead of deploying them separately.
 * Contracts that inherit an abstraction must implement all its method signatures exactly.
 * A contract that only implements part of an inherited abstraction is also considered abstract.

at Deployer._preFlightCheck (/usr/lib/node_modules/truffle/build/webpack:/packages/truffle-deployer/src/deployment.js:178:1)
Truffle v5.0.3 (core: 5.0.3)
Node v11.15.0

I don't really understand, why the contract "organ" is treated as abstract. The same message is occurring , when i try to deploy the contract without the include Statement. So something must be wrong with the contract itself, right? Or have i misunderstood the concept of abstractions completely?

Thanks in regard for help. If further information needed I will extend the post.

  • i just edit my old answer check out and let me know if anything wrong? – haxerl Jun 3 at 4:03
0

It seem like the problem is in your organA.sol interface file you declared an interface: function organAgreementState(bytes32 _organHash) external view returns(bool Agreement); but in your organ.sol you forgot to add that function so that interface is still there and truffle see that it is an interface which haven't been assigned to a real function so it will think that this is just another abstract contract.

And by the way this is not relevant to the topic you ask but i think you should switch to solidity above version 0.5.0 now.

Edit: So okay the way truffle read interface function that it is read the exactly same function that was declared on the interface so if the function even with a slightly change (like variable name) can make truffle confuse and it doesn't link the interface into the function. So in your case, you add modifier to your function but in your interface contract, your interface doesn't have modifier in them, and it make the truffle confuse, so it doesn't link the interface to your actual function. So by remove the modifier in each of your function and put the require inside your function solve the problem. Here what is look like from 1 of your function.

Before:

function getOrgan(bytes32 _organHash) checkOrganExistence(_organHash) public view returns(address OriginOwner, address CurrentOwner, string OrganType, string OrganState) {
        // Return the value
        return (
            organsList[_organHash].originOwner,
            organsList[_organHash].currentOwner,
            organsList[_organHash].organType,
            organsList[_organHash].organState
        );
    }

After:

function getOrgan(bytes32 _organHash) public view returns(address OriginOwner, address CurrentOwner, string OrganType, string OrganState) {
        // Return the value
        require(bytes(organsList[_organHash].organState).length != 0, "Organ with given id doesn't exist!");
        return (
            organsList[_organHash].originOwner,
            organsList[_organHash].currentOwner,
            organsList[_organHash].organType,
            organsList[_organHash].organState
        );
    }
  • Thanks for you reply. Your right. I removed the function signature from the Abstract. But the behavior from Truffle remains the same. Still the same output. I also tried to declare the Abstract as Type Interface but somehow I can't get around this. Do you have any other ideas, what it could be (updated code in questions with your first suggestion). Thanks for the advise. I know that I am using a way outdated Compiler version. Therefor a proper Development environment would help me a lot. – Oliver Jun 2 at 18:07
  • After removing all the modifiers it works, as you suggested. I tried to keep the modifiers the way they are in my contract. But I will need to figure out a way how to do this. Anyways, Thanks for the help! – Oliver Jun 4 at 7:22
0

I think you should deploy organContract not the abstartcontract

abstract contract cannot be compiled and deployed, I guess it is more likely to an interface but you have to implement all Functions

var OrganContract = artifacts.require("./OrganContract.sol");

module.exports = function(deployer) {
    deployer.deploy(OrganContract , {overwrite: true})
};
  • i think you get it wrong, the main contract is the organ.sol. He just didn't name the contract according to the solidity style guide – haxerl Jun 3 at 17:45
  • okay, then he is missing a method – Majd TL Jun 3 at 18:08
  • @MajdTL removing the modifiers within the contract helped solving this issue. – Oliver Jun 4 at 15:34
  • Ah okay it changes the signature of the method :), thanks for the infos @Oliver – Majd TL Jun 4 at 16:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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