Tengo problemas con este modificador y con uno que me gustaría usar para otros contratos. Me imagino que si entiendo por qué esto es un problema, probablemente pueda hacer el resto correctamente.
Puedo compilar, migrar (que también inserta un registro) y probar, pero si uso el modificador onlyOwner, funciona para el registro de migración pero falla en la inserción del registro de prueba. ¿Por qué? ¿La prueba de trufas no usa la misma cuenta que la implementación? y si es así, ¿no debería funcionar?
El modificador que quiero para los otros contratos es algo como esto:
modificador (no funciona del todo):
// 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");
_;
}
código de solidez:
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);
}
}
El problema es que sus pruebas están en solidez y cada prueba es una función en contrato TestCredentialOrgFactory
, y su prueba testInsertCredentialOrg
está llamando a una función enCredentialOrgFactory
function testInsertCredentialOrg() public {
// ... Here msg.sender is web3.eth.accounts[0]
testVal = credentialOrgFactory.createCredentialOrg(...);
}
Dentro testInsertCredentialOrg
del remitente está la dirección predeterminada de su nodo (generalmente la primera cuenta creada), es decir, el propietario o creador de CredentialOrgFactory
.
Llamas credentialOrgFactory.createCredentialOrg()
dentro de un contrato, esto cambia el remitente al contrato de llamadaTestCredentialOrgFactory
function createCredentialOrg(string _shortName, ...)
public onlyOwner
returns (bool createStatus)
{
// ... Here msg.sender is TestCredentialOrgFactory
}
Hay dos soluciones posibles
Vuelva a escribir su prueba en javascript, podrá cambiar quién envía la transacción.
Esta es la solución más flexible a menos que tenga muchas pruebas.
Crea una instancia de tu contrato dentro de tu prueba
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(...);
}
Si su contrato necesita mucha gasolina para implementar su prueba, es posible que no le quede suficiente para ejecutarse.
ismael
sombra