Wie rufe ich eine Funktion aus einem bereits bereitgestellten Vertrag auf?

Ich habe versucht, die Funktion "Anrufen" zu verwenden, wie hier beschrieben: Aufruffunktion aus bereitgestelltem Vertrag

Aber es scheint überhaupt nicht zu funktionieren.

Wie kann ich eine Funktion aus einem vorhandenen bereitgestellten Smart Contract aufrufen?

Ich versuche, eine einfache Funktion von einer vorhandenen Adresse aufzurufen, die eine Adresse als Parameter erhält.

Dies ist der Code, den ich verwende, um die externe Funktion aufzurufen:

Vertrag A:

function CallExternalFunction(address externalContractAddress) 
{    
    externalContractAddress.call(bytes4(sha3("FunctionX(address)")),0xfffff);
    //sends 0xfffff as input parameter to the external contract
}

Der Quellcode des bereits bereitgestellten Vertrags sieht folgendermaßen aus:

Vertrag B:

contract test { 

mapping (address => uint256) public balanceOf; 

function test() { 

}

function FunctionX(address _address)
{
    balanceOf[_address] = 50000;    
}
}
Hast du den Quellcode oder ABI des Vertrages dazu aufgerufen?
Ich habe die Frage mit dem Quellcode aktualisiert
An diesem Ansatz scheint nichts auszusetzen; Es ist nur ein Aufruf auf niedrigerer Ebene an den externen Vertrag. Es gibt nur ein paar Vorbehalte. Ihr callgesamtes Gas (minus ~30.000) wird an den externen Vertrag weitergeleitet, um damit zu tun, was er will, was eine Schwachstelle darstellt, insbesondere wenn der Anruf fehlschlägt und standardmäßig auf die Fallback-Funktion zurückgreift. callunterbricht auch die Typsicherheit für Funktionsargumente und überträgt weiterhin Ether, wenn bei der Ausführung eine Ausnahme ausgegeben wird. Stellen Sie also sicher, dass Sie den Aufruf in a platzieren require(), um Transaktionen rückgängig zu machen, die sich nicht wie erwartet verhalten.

Antworten (1)

Versuche dies. Stellen Sie den Aufrufer bereit, und er stellt den Testvertrag bereit, um die Dinge zu vereinfachen.

contract Caller {

  test public t;

  function Caller() {
    t = new test();
  }

  function callIt(address theAddress)
    public
    returns(bool success)
  {
    t = test(t); <===== here the other contract address can be called t = test([OtherContractAddress]); example: test(0x12345);
    bool result = t.FunctionX(theAddress);
    return result;
  }
}

contract test { 

  mapping (address => uint256) public balanceOf; 

  function FunctionX(address _address) public returns(bool success)
  {
    balanceOf[_address] = 50000; 
    return true;
  }
}

In Remix, um zu zeigen, dass es funktioniert.

Geben Sie hier die Bildbeschreibung ein

Sie können eine ähnliche Struktur für einen Vertrag verwenden, der bereits vorhanden ist, wenn Sie über den Quellcode verfügen, indem Sie einen Schnittstellenvertrag verwenden. Hier kann der "Caller"-Compiler gerade genug von test {} sehen, um die Schnittstelle zu verwalten.

contract Caller {

  test public t;

  // where test is deployed and the address is known
  // Pass in the address for test {}.

  function Caller(address tAddress) {
    t = test(tAddress); // address of contract t
  }

  function callIt(address theAddress)
    public
    returns(uint bal)
  {
      return t.FunctionX(theAddress);
  }
}

// This interface constant includes the function interfaces (exactly as in the "real" contract" with the fynctions undefined
// This tells the compiler how to communicate with the ABI in test{}.

contract test { 
  function FunctionX(address _address) public returns(uint balanceOf) {}
}
Das von Ihnen angezeigte Beispiel scheint die 2 Verträge in derselben bereitgestellten Adresse zu sein, richtig? In meinem Fall werden Vertrag A und B an unterschiedlichen Adressen bereitgestellt (ich habe die Beschreibung mit Vertrag A und B aktualisiert). Wissen Sie, wie es funktioniert, wenn die Verträge an verschiedenen Adressen bereitgestellt werden?
Nein. Zwei Verträge an einer Adresse sind nicht möglich. Zwei Verträge in einer einzigen Quelldatei, wobei der erste Vertrag eine Instanz des anderen bereitstellt (eine Möglichkeit, die Adresse des anderen zu kennen). Anrufer bei 0xb872, Test bei 0x22e6. t = new test();stellt eine neue Instanz von test bereit. Für bereits bereitgestellte Tests{} können Sie die Adresse übergeben oder die Adresse fest codieren. Der Anrufer muss sie kennen, um den Anruf tätigen zu können. Die einzelne Quelldatei gibt dem Compiler eine Ansicht des Testvertrags, damit er die Schnittstelle test{} versteht und über den Bytecode verfügt, den er zum Bereitstellen eines neuen Tests{} benötigt.
Ich mag die Idee der Vorwärtsdeklaration. Beachten Sie, dass der Compiler (solcjs) im obigen Beispiel die Warnung „Unused local variable“ für _address generiert.