Ich möchte wissen, wie ein bestehender Vertrag, der auf der Blockchain bereitgestellt wird, mithilfe seiner Adresse instanziiert wird. z.B:
contract A {
function f1()
{}
}
A
wird auf der Blockchain bereitgestellt, und im Vertrag B
möchte ich die Funktion aufrufen f1()
und ihre Rückgabe erhalten. z.B:
contract B {
address contrac_A=0x123456;
//call f1 from A
}
Wie soll ich es mit der Adresse nennen A
?
Wenn der bereitgestellte Vertrag nicht der ABI entspricht, Sie aber die Vertragssignatur (Name und Argumenttypen) kennen, können Sie Folgendes verwenden:
contract_address.call(bytes4(sha3("function_name(types)")),parameters_values)
zum Beispiel: contrac_A.call(bytes4(sha3("f()"))
Während es in Ihrem Beispiel keine Eingabe gibt, gibt es keine Parameter.
Ersetzen Sie contract_address,function_name,parameters_values durch Ihre Anmeldeinformationen.
Bearbeiten: Da sha3 veraltet ist, ist es besser, stattdessen keccak256 wie folgt zu verwenden:bytes4(keccak256("f()")).
Darüber hinaus wurden seit solidity 0.4.22 die globalen Funktionen abi.encode(), abi.encodePacked(), abi.encodeWithSelector() and abi.encodeWithSignature()
definiert, um strukturierte Daten zu codieren und uns daher dabei zu helfen, gültige Aufrufe zu erstellen (sie geben die erforderlichen 4 Bytes zurück) wie folgt:
contract_address.call.value(1 ether).gas(10)(abi.encodeWithSignature("register(string)", "MyName"));
Dokumentation :
https://github.com/ethereum/wiki/wiki/Solidity-Features#generic-call-method
https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI#function-selector
Weitere Klarstellungen zu @Edmunds Antwort:
contract A { // This doesn't have to match the real contract name. Call it what you like.
function f1(bool arg1, uint arg2) returns(uint); // No implementation, just the function signature. This is just so Solidity can work out how to call it.
}
contract YourContract {
function doYourThing(address addressOfA) returns(uint) {
A my_a = A(addressOfA);
return my_a.f1(true, 3);
}
}
Dies zeigt die Verwendung des Rückgabewerts von f1
.
Wenn f1
eine Ausnahme auftritt (stellen Sie sich vor, ihre Implementierung ist function f1(bool arg1, uint arg2) returns(uint) { throw; }
), wird die Ausnahme weitergegeben und my_a.f1
wird auch throw
eine Transaktion zurücksetzen, die aufgerufen wurde doYourThing
.
In der Praxis haben Sie 3 Dateien.
AbstractA.sol enthält:
contract A {
function f1(bool arg1, uint arg2) returns(uint); // No implementation, just the function signature. This is just so Solidity can work out how to call it.
}
IhrVertrag.sol enthält:
import "AbstractA.sol"
contract YourContract {
function doYourThing(address addressOfA) returns(uint) {
A my_a = A(addressOfA);
return my_a.f1(true, 3);
}
}
A.sol enthält:
contract A {
// implementation of f1
function f1(bool arg1, uint arg2) returns(uint) {
if (arg1) {
throw;
} else {
return arg2;
}
}
}
call
call
wird in der Antwort von @Badr vorgeschlagen, sollte aber sehr vorsichtig verwendet werden. In Solidity -Dokumenten heißt es :
Alle drei Funktionen und sind Funktionen
call
auf sehr niedriger Ebene und sollten nur als letztes Mittel verwendet werden, da sie die Typsicherheit von Solidity verletzen.delegatecall
callcode
Außerdem kann der Rückgabewert von f1
nicht mit call
like abgerufen werden, addressOfA.call(bytes4(keccak256("f1(bool, uint256)")), true, 3)
da call
nur ein bool
( zurückgegeben false
wird, wenn der Aufruf auf eine Ausnahme stößt).
Das bedeutet, dass die Ausnahme wie folgt manuell weitergegeben werden muss:
if (!addressOfA.call(bytes4(keccak256("f1(bool, uint256)")), true, 3)) {
throw;
}
contract A { // This doesn't have to match the real contract name. Call it what you like.
function f1(){} // No implementation, just the function signature. This is just so Solidity can work out how to call it.
}
contract YourContract
function doYourThing() {
A my_a = A(contract_A);
my_a.f1();
}
}
Hier ist ein Solidity-Code für den neuen Vertrag , der die Funktion f1() aus Ihrem alten Vertrag aufrufen kann . Hoffe das hilft. Ich habe versucht, es so einfach wie möglich zu halten.
import "./Old.sol"; // You import the existing contract.
/**
* The NEW contract will call the Old one
*/
contract New {
Old OLD; // Intitilize old contract variable (empty)
/**
* Set the address for Old contract (We call this function and enter the address of the OLD contract)
*/
function setOldContractAddress(address addr) public {
OLD = Old(addr);
}
/**
* Function that allows us to call f1() from the Old contract
*/
function callOLDcontract() public {
OLD.f1();
}
}
Crissi Mariam Robert
Badr Bellaj