Modifer-Vererbung, unerwartetes Ergebnis

Die Einrichtung der Verträge umfasst 3 Verträge: einen Bibliotheksvertrag, einen Controller-Vertrag mit Modifikatoren und einen Hauptvertrag wie folgt:

DataSet.sol  

library DataSet {  

  struct IndexValue { uint keyIndex; uint256 value;}  
  struct KeyFlag { uint key; bool deleted; }  
  struct KeyValue { uint key; uint value; }  


  struct Data {
      mapping(uint => IndexValue) data;  
      KeyFlag[] keys;  
      //KeyValue[] kvpairs;  
      uint size;  
  }  

  function stringToBytes32(string memory source) returns (bytes32 result) {  
      assembly {  
          result := mload(add(source, 32))  
      }  
  }  


  function getCurrent(Data storage self) returns(uint index){  
      return self.size - 1;  
  }  

}  

Controlled.sol:  

contract Controlled {  
    address public userAddr;  

    struct User {  
      address a;  
      string name;  
      string email;  
      uint phone;  
    }  

    mapping (address => User) Users;  

    function registerUser(string _name, string _email, uint _phone) returns (bool success) {  
      Users[msg.sender].a = msg.sender;  
      Users[msg.sender].name = _name;  
      Users[msg.sender].email = _email;  
      Users[msg.sender].phone = _phone;  
    }



    modifier onlyUser {
        if (msg.sender != userAddr) throw;
        _;
    }

}  


contract Main is Controlled {  
  using DataSet for *;    
  DataSet.Data d;  

  struct userProduct {  
    address user_address;  
    uint id;  
    string description;  
    uint price;  
  }  

   userProduct[] products;  


  function newUserProduct  (  
    address u,
    uint i,
    string d,
    uint p) onlyUser returns (bool added) {

    userProduct memory newProduct;
    newProduct.user_address = msg.sender;
    newProduct.id = i;  
    newProduct.description = d;
    newProduct.price = p;
    products.push(newProduct);
    added = true;
  }  

  function getUserInfo (uint g) constant returns (address ,bytes32, uint ) {  
      for (uint i = 0; i <= products.length; i++) {  
          if (products[i].id == g) {  
             return(products[i].user_address, DataSet.stringToBytes32(products[i].description), products[i].price);  
          }  
      }  
  }  
}  

Das Registrieren des Benutzers durch Aufrufen von Controlled.registerUser funktioniert einwandfrei, danach funktioniert das Zuordnen eines Produkts zum Benutzer durch Aufrufen von Main.newUserProduct ebenfalls einwandfrei, um eine tx_id anzugeben. Wenn ich jedoch versuche, getUserInfo aufzurufen, erhalte ich entweder einen ungültigen Sprungfehler, während ich einschiffe, und gebe [0x, 0x, 0x] zurück, während ich truffle verwende. Ich kann das Problem nicht lösen, unabhängig davon, ob es sich um den Modifikator handelt oder ob die Bibliothek nicht korrekt instanziiert wird. Irgendwelche Vorschläge wären immens hilfreich!

Antworten (1)

Ich habe etwas, das dir helfen wird, weiterzumachen.

Der Modifikator

modifier onlyUser {
    if (msg.sender != userAddr) throw;
    _;
}

verhinderte alle Bemühungen, ein Produkt einzustellen, da es userAddrnie eingestellt wurde (==0x0). Es wurde ein Konstruktor hinzugefügt, der sich darum kümmert, und jetzt kann ich ein Produkt hinzufügen.

Danach getUserProduct()angefangen zu arbeiten. Ich habe einigen Zustandsvariablen und einigen Protokollen "öffentlich" hinzugefügt, um zu sehen, was vor sich geht. Achten Sie auf andere kleine Änderungen, die ich möglicherweise beim Debuggen vorgenommen habe.

Einmal gearbeitet. Keine Garantie. :-)

pragma solidity ^0.4.6;

library DataSet {  

  struct IndexValue { uint keyIndex; uint256 value;}  
  struct KeyFlag { uint key; bool deleted; }  
  struct KeyValue { uint key; uint value; }  


  struct Data {
      mapping(uint => IndexValue) data;  
      KeyFlag[] keys;  
      //KeyValue[] kvpairs;  
      uint size;  
  }  

  function stringToBytes32(string memory source) returns (bytes32 result) {  
      assembly {  
          result := mload(add(source, 32))  
      }  
  }  


  function getCurrent(Data storage self) returns(uint index){  
      return self.size - 1;  
  }  

}  

contract Controlled {  
    address public userAddr;  

    struct User {  
      address a;  
      string name;  
      string email;  
      uint phone;  
    }  

    mapping (address => User) public Users;  

    event LogNewUser(address user, string name, string email, uint phone);

    function Controlled() {
        userAddr = msg.sender;
    }

    function registerUser(string _name, string _email, uint _phone) returns (bool success) {  
      Users[msg.sender].a = msg.sender;  
      Users[msg.sender].name = _name;  
      Users[msg.sender].email = _email;  
      Users[msg.sender].phone = _phone;  
      LogNewUser(msg.sender, _name, _email, _phone);
      return true;
    }

    modifier onlyUser {
        if (msg.sender != userAddr) throw;
        _;
    }

}  

contract Main is Controlled {  

  using DataSet for *;    
  DataSet.Data d;  

  struct userProduct {  
    address user_address;  
    uint id;  
    string desc;  
    uint price;  
  }  

  userProduct[] public products; 

  event LogNewUserProduct(address user, uint index, string description, uint price);

  function newUserProduct  (  
    address u,
    uint i,
    string d,
    uint p) onlyUser returns (bool added) {

    userProduct memory newProduct;
    newProduct.user_address = msg.sender;
    newProduct.id = i;  
    newProduct.desc= d;
    newProduct.price = p;
    products.push(newProduct);
    LogNewUserProduct(msg.sender, i, d, p);
    return true;
  }  

  function getUserInfo (uint g) constant returns (address ,bytes32, uint ) {  
      for (uint i = 0; i <= products.length; i++) {  
          if (products[i].id == g) {  
             return(products[i].user_address, DataSet.stringToBytes32(products[i].desc), products[i].price);  
          }  
      }  
  }  
}  

Hier ist es in Remix, um zu zeigen, dass es funktioniert.

Geben Sie hier die Bildbeschreibung ein

Seitenspitze

Es ist schwer zu erkennen, welche Datenstruktur Sie anstreben. Wenn Sie das für mich klären können, schicke ich Ihnen vielleicht eine vereinfachte Version davon zurück.

Es gibt hier Beispielmuster, die helfen könnten: Gibt es gut gelöste und einfache Speichermuster für Solidity?

Zugegeben, es wird ein wenig knifflig, die Muster auf Joins anzuwenden, und es gibt kein verallgemeinertes Beispiel dafür in dem Beitrag.

Ich hoffe es hilft.

Aktualisieren

Ich bin ein wenig verwirrt darüber, wer was tun soll.

onlyAdmin muss in der Lage sein, Attribute zu erstellen/aktualisieren/das Produkt aus dem Struct-Array zu löschen. onlyManager muss in der Lage sein, Attribute zu aktualisieren/das Produkt zu löschen, und onlyTester muss in der Lage sein, die Produktattribute zu aktualisieren

Als Vorsichtsmaßnahme versuche ich im Allgemeinen, Bedenken hinsichtlich der Zugriffskontrolle zu externalisieren. „Besitzer“ kann ein Vertrag sein, der entworfen wurde, um Bedenken hinsichtlich der Zugangskontrolle widerzuspiegeln.

Dieses Gerüst könnte Ihnen einige Ideen geben, wie Sie vorgehen können.

pragma solidity ^0.4.6;

contract Store {

    address public owner;

    enum UserType {owner, admin, tester}

    struct User {
        bytes32 name;
        bytes32 email;
        bytes32 phone;
        UserType userType;
        uint userIndex;
    }

    mapping(address => User) public userStructs;
    address[] public userList;

    struct Product {
        uint price;
        bytes32 description;
        uint productIndex;
    }

    mapping(bytes32 => Product) public productStructs;
    bytes32[] public productList;

    modifier onlyOwner {
        if(msg.sender != owner) throw;
        _;
    }

    modifier onlyAdmin {
        if(!isUser(msg.sender)) throw;
        if(userStructs[msg.sender].userType != UserType.admin) throw;
        _;
    }

    modifier onlyTester {
       if(!isUser(msg.sender)) throw;  
       if(userStructs[msg.sender].userType != UserType.tester) throw;
        _;
    }

    // constructor

    function Store() {
        owner = msg.sender;
    }

    // simple counts

    function getUserCount() public constant returns(uint userCount) { return userList.length; }
    function getProductCount() public constant returns(uint productCount) { return productList.length; }

    // Id checks

    function isUser(address user) 
        public
        constant
        returns(bool isIndeed) 
    {
        if(userList.length == 0) return false;
        return userList[userStructs[user].userIndex] == user;
    }

    function isProduct(bytes32 productId)
        public
        constant
        returns(bool isIndeed)
    {
        if(productList.length == 0) return false;
        return productList[productStructs[productId].productIndex] == productId;
    }

    // inserts

    function createAdmin(address userAddress, bytes32 userName, bytes32 userEmail)
        onlyOwner
        returns(bool success)
    {
        if(isUser(userAddress)) throw;
        userStructs[userAddress].name = userName;
        userStructs[userAddress].email = userEmail;
        userStructs[userAddress].userType = UserType.admin;
        userStructs[userAddress].userIndex = userList.push(userAddress) - 1;
        return true;
    }

    function createTester(address userAddress, bytes32 userName, bytes32 userEmail)
        onlyOwner
        returns(bool success)
    {
        if(isUser(userAddress)) throw;
        userStructs[userAddress].name = userName;
        userStructs[userAddress].email = userEmail;
        userStructs[userAddress].userType = UserType.tester;
        userStructs[userAddress].userIndex = userList.push(userAddress) - 1;
        return true;        
    }

    function createProduct(bytes32 productId, uint productPrice, bytes32 productDescription)
        onlyAdmin
        returns(bool success)
    {
        if(isProduct(productId)) throw;
        productStructs[productId].price = productPrice;
        productStructs[productId].description = productDescription;
        productStructs[productId].productIndex = productList.push(productId);
        return true;
    }

    function updateProduct(bytes32 productId, uint productPrice, bytes32 productDescription)
        onlyTester
        returns(bool success)
    {
        if(!isProduct(productId)) throw;
        if(isProduct(productId)) throw;
        productStructs[productId].price = productPrice;
        productStructs[productId].description = productDescription;
        productStructs[productId].productIndex = productList.push(productId);
        return true;        
    }

}
Ich strebe eine Datenstruktur an, in der ich eine beliebige Anzahl von Benutzern hinzufügen, aber nach Rollen klassifizieren kann. Und entsprechend Modifikatoren setzen. Zum Beispiel Benutzertyp Admin, Business Manager und Tester. Jeder von ihnen sollte sich über Controlled.sol registrieren können, und die Funktionen in Main haben entsprechende Funktionalitäten, dh onlyAdmin, onlyManager und onlyTester. Hoffentlich macht diese Frage Sinn
Wo passen die Produkte hinein? Benutzer:Produktbeziehung.
Grundsätzlich muss nur der Administrator in der Lage sein, Attribute zu erstellen/aktualisieren/das Produkt aus dem Struct-Array zu löschen. onlyManager muss in der Lage sein, Attribute zu aktualisieren/das Produkt zu löschen, und onlyTester muss in der Lage sein, die Produktattribute zu aktualisieren
Danke für das Update! das war sehr hilfreich. Ich habe die Produktteile in einen neuen Vertrag aufgeteilt, der vom Store-Vertrag erbt. Ich konnte es auf dem Online-Solidity-Compiler kompilieren und ausführen. Ich habe einen Getter hinzugefügt, um die Produktinformationen abrufen zu können, was auf dem Online-Compiler gut funktioniert hat. Wenn ich jedoch dasselbe in truffle/embark ausführe, erhalte ich entweder leere Ergebnisse wie ['0x','0x'] oder einen ungültigen Sprungfehler. Nicht sicher, was das Problem ist.