La salida de la función heredada del contrato inteligente de Solidity falló

Estoy tratando de heredar una función del contrato principal en el contrato secundario y funciona bien en la VM de JavaScript remix. Hice los siguientes pasos:

  1. Implementó el contrato principal en la VM de JavaScript remix.
  2. almacenó algunos valores aleatorios ejecutando la storeValuefunción del contrato principal
  3. copié la dirección del contrato principal y lo instalé en el contrato secundario Ahora, si llamo a la getValuefunción del contrato secundario que básicamente está llamando a la función de obtener valor almacenado del contrato principal, la salida es una matriz de valores y todo funciona perfectamente bien .


PERO

Si implemento ambos contratos en la cadena de bloques privada, obtengo una matriz de valores vacía. Hice los siguientes pasos:

  1. comenzó la cadena de bloques privada (cliente geth)
  2. Cambia el entorno a Web3 Provider en el remix
  3. implemente el código WEB3DEPLOY de remix en cadena privada y copie la dirección de la dirección extraída de la cadena privada
  4. usó la dirección para instanciar el contrato principal en el contrato secundario
  5. repitió el proceso de despliegue para el contrato infantil
  6. alimentar los valores usando web3.py en python jupyter notebook


Ahora, si llamo directamente a la función accountTxdesde el contrato principal en la interfaz, funciona bien. Pero, si llamo a la función heredada getValuedel contrato secundario en la interfaz, el resultado es una matriz vacía.
Entonces, el problema es que no puedo obtener el resultado de la función getValueque llama a la función desde otro contrato cuando se implementa en una cadena privada. Pero funciona bien en remix JavaScript VM.
Contrato de padres:

pragma solidity ^0.4.20;

contract Parent {

    uint256[] values;
    mapping (address => uint256[])transactions;


    function storeValue(uint256 _value) {

        transactions[msg.sender].push(_value);
    }

    function accountTx(address addr) constant returns(uint256[]) {

        return (transactions[addr]);
    }

}


Contrato de niño:

pragma solidity ^0.4.20;

import './Parent.sol';


contract Child {

  /* instantiating parent contract*/
  Parent p = Parent(0x9dd1e8169e76a9226b07ab9f85cc20a5e1ed44dd);


   function getValue() public view returns (uint256[]){
      return p.accountTx(msg.sender);
  }

}

Creé la instancia del contrato principal como global porque quiero usarla para algunas funciones.
¿Me falta algo como declarar la función como un external? Cualquier orientación definitivamente sería apreciada, gracias.

Respuestas (1)

Sospecho que tal vez malinterpretas la herencia de "el contrato".

Hay dos ideas diferentes que se parecen. Considerémoslos:

  1. Hay un contrato A y un contrato B y necesitan comunicarse. A no es B y B no es A, pero A necesita suficiente información sobre B para comunicarse con él, y viceversa.
  2. Hay un fragmento de código reutilizable que se ocupa de un problema de bajo nivel. Será útil importarlo en muchos contratos para que puedan "heredar" la lógica.

Esas son dos preocupaciones completamente separadas.

Puede hacer un fragmento de código reutilizable (deliberadamente incompleto para mantener las cosas en orden):

Imparable.sol

contract Stoppable {

    bool public isRunning;

    modifier onlyIfRunning {
        require(isRunning);
        _;
    }

    function Stoppable() public {
        isRunning = true;
    }

    function setRunSwitch(bool newSetting) public returns(bool contractRunning) {
        isRunning = newSetting;
    }
}

Excelente. Ahora bien, si queremos que A o B sean parables, solo vamos contract A is Stoppable {...y agregamos el onlyIfRunningmodificador a las funciones de cambio de estado que queremos proteger. Aobtendrá la variable de estado isRunningasí como la función setRunSwtich()porque hereda el código y su constructor se ejecuta cada vez que Ase implementa an.

Ahora, considere el otro caso. Bquiere inspeccionar algo sobre A, o Bquiere enviar una transacción a A. No se trata de herencia. Se trata de que B tenga suficiente información para hablar con una instancia A.

B necesita

  1. Las firmas de función utilizadas por A
  2. La dirección de una instancia de A (¿dónde se implementó?)

a.sol

contract A {

  bytes32 public something;

  function setSomething(bytes32 newThing) public {
    something = newThing;
  }
}

B.sol

contract B {

  A a; // Type A (source available in the contract above), called "a"

  function B(address aAddress) public { // inform B where it can find an instance of A
    a = A(aAddress);
  }

  function getSomethingFromA() public view returns(bytes32 theThing) {
    return a.something();
  }
}

Eso no se va a compilar al principio, porque Ano está definido. En B.solti lo harías

import "./A.sol"; 

Eso es para que el compilador pueda verlo y descubrir la información de interfaz que necesita B. Tenga en cuenta que no estamos diciendo nada como B is A.

En caso de que lo anterior sea demasiado abstracto, considere un sistema de entradas para conciertos, bandas, lugares y eventos, cada uno representado en un conjunto de contratos entrelazados. Puede ser conveniente hacer que los contratos hereden un conjunto común de permisos y contratos de administración, como la idea Stoppable. Los contratos entrelazados como Eventos pueden inspeccionar Bandas y Lugares para confirmar que las cosas tengan sentido, por lo que necesitarán un poco de conocimiento de las interfaces y el paradero.

No parecería sensato decir Evento es Venue, o Venue es Band. Cuando comienza a torcerse así, es una señal de mal uso de la herencia.

Espero eso ayude.