Hilfe bei Vererbung und Trüffeltests

Ich habe zwei Verträge, die beide von der Whitelist von OpenZeppelin erben . Nachdem ich beide Verträge bereitgestellt habe, verwende ich eine Instanz des ersten Vertrags, um der Whitelist eine „vertrauenswürdige“ Adresse hinzuzufügen. Da beide Verträge von derselben Whitelist erben, würde ich davon ausgehen, dass der zweite Vertrag auch sieht, dass „trusted“ auf der Whitelist steht. Beim Testen sehe ich das aber nicht. Meine Fragen stehen unter dem Code.

Verträge A und B :

pragma solidity ^0.4.23;
import "openzeppelin-solidity/contracts/ownership/Whitelist.sol";

contract A is Whitelist {   
}

contract B is Whitelist {   
}

Migration 2_deploy.js :

var A = artifacts.require("./A.sol");
var B = artifacts.require("./B.sol");

module.exports = function(deployer, network, accounts) {
    var owner = accounts[0];
    var trusted = accounts[1];

    deployer.deploy(A, {from: owner})
    .then(function(){
        console.log("A deployed");  
        return; 
    });

    deployer.deploy(B, {from: owner})
    .then(function(){
        console.log("B deployed");      
        return;
    });

    A.deployed()
    .then(function(instance) {
        instance.addAddressToWhitelist(trusted, {from: owner})
        .then(function() {
            return;
        });
    });
};

test.js :

const A = artifacts.require("A");
const B = artifacts.require("B");

contract('A', async (accounts) => {
    let owner = accounts[0];
    let trusted = accounts[1];

    a = await A.deployed();
    b = await B.deployed();

    let isWhitelistedA = await a.whitelist(trusted); 
    let isWhitelistedB = await b.whitelist(trusted); 
    console.log("before adding trusted, contract A: "+isWhitelistedA); 
    console.log("before adding trusted, contract B: "+isWhitelistedB); 

    await a.addAddressToWhitelist(trusted, {from: owner});
    isWhitelistedA = await a.whitelist(trusted); 
    isWhitelistedB = await b.whitelist(trusted); 
    console.log("after adding trusted to A, contract A: "+isWhitelistedA);
    console.log("after adding trusted to A, contract B: "+isWhitelistedB);

    await b.addAddressToWhitelist(trusted, {from: owner});
    isWhitelistedA = await a.whitelist(trusted); 
    isWhitelistedB = await b.whitelist(trusted); 
    console.log("after adding trusted to B, contract A: "+isWhitelistedA);
    console.log("after adding trusted to B, contract B: "+isWhitelistedB);  
})

Ergebnis des Trüffeltests:

before adding trusted, contract A: false
before adding trusted, contract B: false
after adding trusted to A, contract A: true
after adding trusted to A, contract B: false
after adding trusted to B, contract A: true
after adding trusted to B, contract B: true

Fragen:

  1. Warum wird Trusted nicht auf die Whitelist gesetzt, bevor es zum Test hinzugefügt wird ? Die Migration hätte es hinzufügen sollen.
  2. Wenn vertrauenswürdig über die Instanz von A auf die weiße Liste gesetzt wird, warum wird sie nicht gemäß B auf die weiße Liste gesetzt ? Dafür hätte das Erbe sorgen müssen.

Anmerkungen:

  • Das könnte sein, dass ich nicht verstehe, wie "bereitgestellt" und Instanzen funktionieren, also kläre mich bitte auf, was passiert :).
  • test.js ist offensichtlich kein richtiger Truffle-Test (da nichts wirklich getestet wird), aber es ist ein reduziertes Beispiel für ein Problem, mit dem ich konfrontiert bin.

Andere Information:

  • Trüffel v4.1.8 (Kern: 4.1.8)
  • Solidität v0.4.23 (solc-js)
  • Verwenden von Ganache mit localhost

Antworten (1)

Kurze Antwort: Beide Verträge erstellen neue Instanzen von Whitelist. Sie teilen sich nicht dieselbe Instanz.

Um dieselbe Instanz gemeinsam zu nutzen, müssen beide auf dieselbe Adresse einer einzelnen bereitgestellten Whitelist.

Indem Sie beide Verträge einsetzen, verschwenden Sie tatsächlich (wie klein oder groß) Gas, da beide Verträge redundanten Code haben.

Mein Vorschlag (der zu Ihrem Anwendungsfall passen kann oder nicht) ist:

  • habe nur den vertrag Aerben Whitelist.
  • Erstellen Sie einen neuen Vertrag, der die Funktionen dieses Vertrags interfaceauflistet , die genutzt werden müssen. Der Vertrag wird einen variablen Typ dieses Vertrags haben.WhitelistBBinterface
  • Setzen Sie die Vertragsadresse Aauf die Vertragsvariable , hat Balso Bjetzt einen Verweis auf dieWhitelist

Sie sind möglicherweise ein besseres architektonisches Design für Ihr Problem - Aber damit wird Ihr Sandbox-Beispiel funktionieren.

Code snippets:

WhitelistInterface.sol

Vertrag B:

import "./WhitelistInterface.sol";

WhitelistInterface whitelistInstance;

BKonstruktor:

require(_whitelistAddress != address(0));
whitelistInstance = WhitelistInterface(_whitelistAddress);

BFunktionsaufruf für Whitelisting

bool isWhitelisted = whitelistInstance.whitelist(addressToTest);
Hinweis: Der Vertrag Bhat nur Lesezugriff, da es sich nicht um eine ownerder whitelist. Sie werden also gezwungen sein, Verträge Afür onlyOwnerFunktionen zu verwenden, es sei denn, Sie ändern den Code.
Richtig ... Ich verstehe jetzt den folgenden Satz aus Solidity Docs besser: When a contract inherits from multiple contracts, only a single contract is created on the blockchain, and the code from all the base contracts is copied into the created contract. Das würde bedeuten, dass der Code von Whitelisttatsächlich sowohl in als auch dupliziert wird , Awobei Bjeder seinen eigenen Status hat.