onlyOwner und Prüfungsfrage

Ich kämpfe mit diesem Modifikator sowie mit einem, den ich für einige andere Verträge verwenden möchte. Ich denke, wenn ich verstehe, warum dies ein Problem ist, kann ich wahrscheinlich den Rest richtig machen.

Geben Sie hier die Bildbeschreibung ein

Ich kann kompilieren, migrieren (was auch einen Datensatz einfügt) und testen, aber wenn ich den Modifikator onlyOwner verwende, funktioniert er für den Migrationsdatensatz, schlägt jedoch beim Einfügen des Testdatensatzes fehl. Warum? Wird beim Trüffeltest nicht dasselbe Konto wie beim Deployment verwendet? und wenn ja sollte das nicht funktionieren?

Geben Sie hier die Bildbeschreibung ein

Der Modifikator, den ich für die anderen Verträge haben möchte, sieht ungefähr so ​​​​aus:
Modifikator (funktioniert nicht ganz):

// modifiers  
/**
* @dev Modifer onlyBy for Access Control
*/
modifier onlyBy(address _credentialOrgAddress){
    uint32 foundAccount = 0;
    CredentialOrgFactory cof = CredentialOrgFactory(credentialOrgContractAddress);
    if (cof.isCredentialOrg(_credentialOrgAddress)){
        foundAccount = 1;
    }
    require(foundAccount == 1, "Not Credentialing Org");
    _;
}

Soliditätscode:

pragma solidity ^0.4.21;  

/**
 * @title CredentialOrgFactory
 * @dev The CredentialOrgFactory allows the contract owner to add new credentialing orgs  */  
import "./Pausable.sol";  
import "./SafeMath32.sol";  

contract CredentialOrgFactory is Pausable {

/**
*  @dev Library useage for safemath for uint32
*/
using SafeMath32 for uint32;

/**
* @dev mappings
*/
mapping(address => CredentialOrg) addressToCredentialOrg;

/**
* @dev events for contract
* One for the create CredentialOrg and one for the basic 'logging'.
*/
event CredentialOrgCreateEvent(string shortName, address schoolAddress, string detail);
event CredentialOrgEvent(address schoolAddress, string detail);

/**
* @dev CredentialOrg Count
*/
uint32 private credentialOrgCount;

/**
* @dev Primary CredentialOrg structure, and following array.
*/
struct CredentialOrg {
    string shortName;          // School shortName (len 30)
    string officialSchoolName; // official school shortName (70 or less)
    address schoolAddress;
}

CredentialOrg[] private credentialOrgs; // array to hold Credentialing Orgs

/**
* @dev class constructor
*/
constructor() public {
    credentialOrgCount = 0;
}

// functions
function getOwner()
public view
returns (address returnedOwner)
{
    returnedOwner = owner;
}

/**
* @dev allows owner to create new credentialing orgs
* @param _shortName shortName of Credentialing orgs
* @param _officialSchoolName official School Name
* @param _schoolAddress address of credential org.
* @return createStatus bool noting creation status success or failure
*/
function createCredentialOrg(string _shortName, string _officialSchoolName, address _schoolAddress) //onlyOwner
public 
returns (bool createStatus)
{
    emit CredentialOrgCreateEvent(_shortName, _schoolAddress, "New Org Add (PRE)");
    require(bytes(_shortName).length > 0 && bytes(_shortName).length < 31, "createCredentialOrg shortName problem");
    require(bytes(_officialSchoolName).length > 0 && bytes(_officialSchoolName).length < 70, "createCredentialOrg officalSchoolName length problem");
    require(_schoolAddress != 0, "createCredentialOrg (FAIL) school Address can not be 0");
    createStatus = false;
    uint32 position = uint32(credentialOrgs.push(CredentialOrg(_shortName, _officialSchoolName, _schoolAddress)));
    if (position > 0){
        addressToCredentialOrg[_schoolAddress] = credentialOrgs[position.sub(1)];
        credentialOrgCount = credentialOrgCount.add(1);
        createStatus = true;
        emit CredentialOrgCreateEvent(_shortName, _schoolAddress, "createCredentialOrg (SUCCESS)");
    } else {
        emit CredentialOrgCreateEvent(_shortName, _schoolAddress, "createCredentialOrg (FAIL)");
    }
    return (createStatus);
}

/**
* @dev allows selection of a credentialingOrg by position
* @param _credentialOrgPosition allows selection of credentialing orgs details.
* @return shortName - shortName of Credential Org
* @return officialSchooName - official school name
* @return school -the schools ethereum address 
*/
function selectCredentialOrgByPosition(uint32 _credentialOrgPosition) 
public view 
returns (string shortName, string officialSchoolName, address schoolAddress)
{
    shortName = "";
    officialSchoolName = "";
    schoolAddress = 0;
    require(_credentialOrgPosition >= 0, "selectCredentialOrg - position had to be greater or equal to 0.");
    if (_credentialOrgPosition < credentialOrgCount){
        emit CredentialOrgEvent(msg.sender, "selectCredentialOrg~position - (SUCCESS)");
        return (credentialOrgs[_credentialOrgPosition].shortName, credentialOrgs[_credentialOrgPosition].officialSchoolName, credentialOrgs[_credentialOrgPosition].schoolAddress);
    } else {
        emit CredentialOrgEvent(msg.sender, "selectCredentialOrg~position - (FAIL) top boundry exceeded.");
        return (shortName, officialSchoolName, schoolAddress);
    }
}

/**
* @dev allows selection of a credentialingOrg by address
* @param _credentialOrgAddress allows selection of credentialing orgs details.
* @return shortName - shortName of Credential Org
* @return officialSchooName - official school name
* @return school -the schools ethereum address 
*/
function selectCredentialOrgByAddress(address _credentialOrgAddress) 
public view 
returns (string shortName, string officialSchoolName, address schoolAddress)
{
    require(_credentialOrgAddress != 0, "selectCredentialOrg - Address 0 not valid");
    CredentialOrg memory testCred = addressToCredentialOrg[_credentialOrgAddress];
    if (testCred.schoolAddress != 0){
        emit CredentialOrgEvent(msg.sender, "selectCredentialOrg~address - (SUCCESS)");
        return (testCred.shortName, testCred.officialSchoolName, testCred.schoolAddress);
    } else {
        emit CredentialOrgEvent(msg.sender, "selectCredentialOrg~address - (FAIL)");
        return ("", "", 0);
    }
}

/**
* @dev allows checking if credentialOrg exists
* @param _credentialOrgAddress function returns bool if an address is a credentialingOrg
* @return isAddress returns true if address is Credentialing Org, false if not.
*/
function isCredentialOrg(address _credentialOrgAddress) 
public view
returns (bool isOrgAddress)
{
    isOrgAddress = false;
    CredentialOrg memory testCredentialOrg = addressToCredentialOrg[_credentialOrgAddress];
    if (testCredentialOrg.schoolAddress != 0){
        isOrgAddress = true;
        emit CredentialOrgEvent(msg.sender, "isCredentialOrg - (SUCCESS)");
    } else {
        emit CredentialOrgEvent(msg.sender, "isCredentialOrg - (FAIL)");
    }
    return (isOrgAddress);
}

/**
* @dev returns the credentialOrgCount
* @return returnOrgCount - returns the total credential orgs count
*/
function selectOrgCount()
public view
returns (uint32 returnOrgCount)
{
    returnOrgCount = credentialOrgCount;
    emit CredentialOrgEvent(msg.sender, "selectOrgCount - (SUCCESS)");
    return (returnOrgCount);
}

}
Was machst du in den fehlgeschlagenen Tests?
Erstellen einer credentialOrg. Ich habe das Git-Repository aktualisiert, um es zu demonstrieren, und alles außer dem ersten Vertrag auskommentiert. Die einzige Abweichung beim Testen ist der Modifikator onlyOwner. [ github.com/shaddow1201/CredentialVerify] (GitHubLink zum Projekt) Hier ist das Ganache-Setup: screencast.com/t/3p9dlHeDI und detaillierte Fehler: screencast.com/t/9lpwXtiE0

Antworten (1)

Das Problem ist, dass Ihre Tests solide sind und jeder Test eine Funktion im Vertrag ist TestCredentialOrgFactoryund Ihr Test testInsertCredentialOrgeine Funktion aufruftCredentialOrgFactory

function testInsertCredentialOrg() public {
    // ... Here msg.sender is web3.eth.accounts[0]
    testVal = credentialOrgFactory.createCredentialOrg(...);

}

Innerhalb testInsertCredentialOrgdes Absenders befindet sich die Standardadresse Ihres Knotens (normalerweise das zuerst erstellte Konto), dh der Besitzer oder Ersteller von CredentialOrgFactory.

Rufen Sie credentialOrgFactory.createCredentialOrg()innerhalb eines Vertrages an, ändert dies den Absender zum anrufenden VertragTestCredentialOrgFactory

function createCredentialOrg(string _shortName, ...) 
public onlyOwner
returns (bool createStatus)
{
    // ... Here msg.sender is TestCredentialOrgFactory
}

Es gibt zwei mögliche Lösungen

  1. Schreiben Sie Ihren Test in Javascript neu, Sie können wechseln, wer die Transaktion sendet.

    Dies ist die flexiblere Lösung, es sei denn, Sie haben viele Tests.

  2. Instanziieren Sie Ihren Vertrag in Ihrem Test

    function testInsertCredentialOrg() public {
        // The owner of credentialOrgFactory is TestCredentialOrgFactory
        CredentialOrgFactory credentialOrgFactory = new CredentialOrgFactory(...)
    
        // This call should succeed because the owner is TestCredentialOrgFactory
        testVal = credentialOrgFactory.createCredentialOrg(...);
    
    }
    

    Wenn Ihr Vertrag viel Gas zum Bereitstellen benötigt, ist für Ihren Test möglicherweise nicht mehr genug übrig, um ausgeführt zu werden.

werde jetzt daran arbeiten. anerkennen. Ich hatte erwartet, irgendwann zum Testen den JS-Weg gehen zu müssen, hoffte aber, das Arbeitsset zumindest bis zum Abschluss des Unterrichts so klein wie möglich zu halten. Hatte nicht daran gedacht, innerhalb des Tests zu instanziieren, werde das zuerst versuchen. Ich kann davonkommen, wenn ich nicht onlyOwner im CredentialOrgFactory-Vertrag habe, aber nicht die anderen Verträge, die isCredentialOrg für die Zugriffskontrolle verwenden.
das hat funktioniert! hinzugefügt: // regelmäßige Tests CredentialOrgFactory credentialOrgFactoryA = CredentialOrgFactory(DeployedAddresses.CredentialOrgFactory()); // onlyOwner testet CredentialOrgFactory credentialOrgFactoryB = new CredentialOrgFactory();