Ich kann ein Problem nicht ganz herausfinden, das verhindert, dass Contract-to-Contract-Funktionsaufrufe ausgeführt werden.
Ich bin ziemlich zuversichtlich, dass es etwas mit meiner Bereitstellung zu tun hat.
Vorwort: Ich habe einen Parent
und- Child
Vertrag, wo das Kind Anrufe der Eltern aufrufen kann. Das untergeordnete Element enthält eine Adresse des übergeordneten Elements, die nach der Bereitstellung festgelegt wird und aktualisierbar sein sollte, falls ein neuer Parent
Vertrag bereitgestellt wird.
pragma solidity >0.4.23 <0.5.0;
interface IParent {
function setValue(int v) external;
function getValue() external view returns (int);
function getSender() external view returns (address);
}
Parent.sol
pragma solidity >0.4.23 <0.5.0;
import "./IParent.sol";
contract Parent is IParent {
int value;
function setValue(int v) public {
value = v;
}
function getValue() external view returns (int) {
return value;
}
function getSender() external view returns (address) {
return msg.sender;
}
}
Kind.sol
pragma solidity >0.4.23 <0.5.0;
import "./IParent.sol";
contract Child {
IParent parent;
function setParent(address a) public {
parent = IParent(a);
}
function getValue() external view returns (int value) {
return parent.getValue();
}
function getSender() external view returns (address value) {
return parent.getSender();
}
}
(Ich verwende Mist, um die Bereitstellung durchzuführen, um Probleme zu vermeiden, die ich möglicherweise eingeführt habe, und versuche, das Problem zu isolieren. Ich erhalte auch das gleiche Ergebnis, wenn ich web3js bereitstelle.)
Verträge zusammenstellen:
solc --bin Child.sol Parent.sol
Stellen Sie die Verträge bereit
Binary:
Abschnitt für Child.sol
in den Abschnitt „Vertragsbereitstellung“ von Mist CONTRACT BYTE CODE
und stellen Sie ihn bereitParent.sol
Holen Sie sich das ABI:
solc --abi Child.sol Parent.sol
Sehen Sie sich die Verträge an:
Contract JSON ABI
Abschnitt für zusammen mit der entsprechenden Adresse Child.sol
in Mist'sWATCH CONTRACT
Parent.sol
Verknüpfen Sie die Verträge
Child
Vertrag aussetParent
mit der Adresse des übergeordneten Vertrags ausLegen Sie den Wert in Parent fest:
Parent
Vertrag aussetValue
mit 999 oder etwas anderem als 0 ausWenn Sie von hier aus den Child
Vertrag anzeigen, spiegeln sowohl die Werte value
als auch msg.sender
die Standardwerte wider.
Ich habe auch Folgendes versucht, innerhalb der Child
:
function getValueSuccess() external view returns (bool) {
return parentAddress.call(bytes4(keccak256("getValue()")));
}
Dies kehrt zurück true
, aber das Folgende kehrt immer zurück 0
:
function getDummyValue() external view returns (int) {
parent.getValue();
return 999;
}
Verwenden Sie auch die folgenden Montagearbeiten:
function getValue() external view returns (int value) {
address addr = address(parent);
bytes4 sig = bytes4(keccak256("getValue()"));
assembly {
let o := mload(0x40) // Empty storage pointer
mstore(o,sig) // Push function signature to memory (function signature is 4 bytes/0x04)
//mstore(add(ptr,0x40), someInt32Argument); // Append function argument after signature
// From here, the call data size (input) would be functiona signature size + sum(argument size)
// 4bytes + 0 in this case, or 4bytes + 32bytes in the above commented `mstore`
let success := call(
15000, // Gas limit
addr, // To address
0, // No ether to transfer
o, // Input location ptr
0x04, // Input size (0)
o, // Store oputput over input
0x20) // Output size (32 bytes)
value := mload(o)
mstore(0x40,add(o,0x04))
}
}
Es scheint, als würde die Umwandlung von der übergeordneten Adresse in IParent
nicht funktionieren, da alle Aufrufe fehlzuschlagen scheinen, es sei denn, wir verwenden Assembly oder address.call()
, von denen ich annehme, dass sie nur die Nachricht an die Adresse senden und die Typbeschränkung vermeiden (wie die Verwendung von Reflektion).
Wenn ich einfach alle Verträge in einer einzigen Datei zusammenführe, kopiere und füge diese in Mists SOLIDITY CONTRACT SOURCE CODE
Box ein und stelle jeden von ihnen aus der Dropdown-Liste bereit. Alles funktioniert wie erwartet.
Welche Schritte fehlen mir oben, damit dies wie erwartet funktioniert?
Wenn ich einen funktionierenden Satz von Verträgen bereitstelle, Mist verwende, um den Quellcode bereitzustellen, und dann die Parent
Binärdatei in Mist bereitstelle, kann ich sie erfolgreich vom Kind aus verknüpfen/aufrufen.
Es sieht also nach etwas Speziellem mit dem Child
Deployment aus.
Dies funktioniert nur mit obigem Testvertrag. Nachdem ich dies in meinen eigentlichen Vertrag verschoben habe, stehe ich vor dem gleichen Problem
Ich bin auf diese Frage gestoßen , wo @smarx geantwortet hatte mit:
FYI, Sie können dies stattdessen tun (und es von einem Client auf die gleiche Weise aufrufen):
NonFungibleToken public nft;Funktion setNFTAddress (NonFungibleToken _nft) onlyOwner{
nft = _nft;
}
Aus irgendeinem Grund scheint dies zu funktionieren, während das einfache Übertragen der Adresse in den Vertrag nicht funktioniert?
Warum sollte das funktionieren:
function setParent(Parent p) external {
parent = p;
}
aber nicht das:
function setParent(address addr) external {
parent = Parent(addr);
}
... und noch verwirrender, warum sollten sie beide funktionieren, wenn sie mit dem Quellcode in Mist bereitgestellt werden, und nur die erste Arbeit, wenn sie die Binärdateien verwenden?
Versionen:
Aktivieren Sie neue EVM-Funktionen, indem Sie Folgendes Byzantium
zum config
Abschnitt Ihrer hinzufügen genesis.json
:
"config": {
"chainId": 1234,
"homesteadBlock": 0,
"eip155Block": 0,
"eip158Block": 0,
"eip160Block": 0,
"byzantiumBlock": 0
},
Danke an @chriseth von Solidity für die Hilfe bei der Suche
Benutzer19510
Benutzer19510
Nulik
Justin
js
.Justin
Child
. Stellen Sie die Verträge einfach erneut bereit, indem Sie die Quellcodemethode in Mist anstelle von Binärdateien verwenden. Verknüpfen Sie dann das untergeordnete Element mit einem der vorherigen übergeordneten Verträge, der mithilfe der binären Methode bereitgestellt wurde. Das scheint zu funktionieren, es sind nur alleChild
Verträge, die mit der binären Methode bereitgestellt wurden.Justin
solcjs
, . Gleiches Ergebnis, no go.Benutzer19510
Justin
Parent(addr)
. Ich hatte eine Ansichtsfunktion wie hinzugefügtfunction testCast(address p) returns (int) { Parrent parent = Parent(p); parent.setValue(9); return 1; }
. Wenn diese Funktion aufgerufen wird,0
ist immer der Rückgabewert.Justin
getValue
Funktion als auch die Assembly mit dem Namen einbeziehe,getValueAssembly
funktioniert eine und die andere nicht.