msg.sender gibt 0x0000000000000000000000000000000000000000 zurück

Dieser Vertrag sollte die Adresse des Absenders zurückgeben:

contract SimpleExample {
    function getSender() constant returns (address) {
        return msg.sender;
    }
}

Das folgende Javascript ruft diesen Vertrag auf:

var abi = [{"constant":true,"inputs":[],"name":"getSender","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"}]
var MyContract = web3.eth.contract(abi);
var myContractInstance = MyContract.at('0x46E286cb00c5e7D5949D18e767447E513d001BBA');

myContractInstance.getSender.call(function(error, result){
    if(!error) {
        console.log("##" + result + "##")
    } else {
        console.error("Error:" + error);
    }
})

Anstatt die Adresse des Absenders zurückzugeben, wird 0x000000000000000000000000000000000000000 zurückgegeben.

.callerstellt keine Transaktion. Es ruft die Funktion lokal auf dem Client auf. Es gibt keinmsg
Ihr getSenderist eine konstante Funktion. Standardmäßig erstellt web3 keine Transaktion zum Aufrufen einer konstanten Funktion. Sie entfernen entweder das constantSchlüsselwort oder rufen .getSender.sendTransactionan, um web3 zu zwingen, eine TX zu senden. Außerdem erhalten Sie immer noch nicht den Rückgabewert von einer tx-Quittung. Sie sehen nur Ereignisprotokolle, wenn Sie welche haben
Das gleiche Problem tritt auf, wenn ich die Funktion so aufrufe: "myContractInstance.getSender(function(error, result){" Viele Solidity-Beispiele verwenden den msg.sender-Wert in ihren Beispielfunktionen, die keine Transaktionen erstellen, sondern nur Daten abrufen Beispielsweise schlagen sie vor, dass der Konstruktor der Funktion den msg.sender-Wert in einer globalen 'Creator'-Variable speichert, was ebenfalls nicht zu funktionieren scheint, denn wenn ich dann versuche, die 'Creator'-Variable in einer separaten Funktion abzurufen, gibt sie 0x0 zurück.
Der Rückgabewert der Funktionen wird nicht in der TX-Quittung angezeigt. Es ist für Verträge gedacht. Verwenden Sie Ereignisse, wenn Sie möchten, dass Daten in der Sendebestätigung angezeigt werden.
Wenn Sie auf eine Speichervariable zugreifen möchten, machen Sie es publicdann wiemyContractInstance.creator()
Als ich das Schlüsselwort „constant“ entfernte, gab es immer noch 0x0 zurück. Der Konstruktor des Vertrags speichert den msg.sender-Wert auch nicht in einer globalen „Creator“-Variablen. Geben Sie bitte ein einfaches Beispiel an, wie ein Vertrag den msg.sender-Wert zurückgeben kann.

Antworten (1)

Derzeit gibt es 3 Möglichkeiten, eine Vertragsfunktion in web3 "aufzurufen".

  • Sie können es mit aufrufen myContractInstance.foo.call(), wodurch web3 den Vertragscode lokal ausführt (da der Bytecode für alle Blockchain-Teilnehmer sichtbar ist). Es gibt Ihnen den Rückgabewert zurück, indem es die Funktion lokal ausführt . Es erstellt keine TX, sendet nichts an das Netzwerk. Es gibt keine Nachricht.
  • Sie können es mit aufrufen myContractInstance.foo.sendTransaction(), wodurch web3 einen tx sendet, um die Funktion aufzurufen. Es gibt Ihnen einen tx-Hash zurück . Sie müssen für Benzin bezahlen, warten, bis der TX abgebaut ist, dann erhalten Sie Ihre TX-Quittung. Beachten Sie, dass Sie auf diese Weise nicht den Rückgabewert der Funktion erhalten, da sie nicht in der TX-Quittung enthalten sind. Protokolle sind jedoch in der tx-Quittung.
  • Sie können einfach mit anrufen myContractInstance.foo(). Wenn Ihre Funktion lautet constant, verwendet web3 .call. Wenn es nicht konstant ist, wird es verwendet.sendTransaction

Damit das Beispiel in einem Web3-Client funktioniert, müssen Sie

  • Machen Sie die Funktion nicht konstant
    • Denn sonst würde web3 keine Transaktion senden, um diese Funktion aufzurufen. (Obwohl Sie es mit erzwingen können .sendTransaction)
  • Lassen Sie die Funktion ein Ereignis protokollieren
    • Weil Funktionsrückgabewerte nicht in der TX-Quittung angezeigt werden. Nur Protokolle sind. Rückgabewerte sind für Verträge gedacht, und Sie können sie auch in konstanten Funktionen verwenden, wenn Sie .callsich in Ihrem Client befinden. (Sie können es hier nicht tun, wenn Sie .calldann kein msg)

Modifiziertes Beispiel

contract SimpleExample {
    event LogSender(address sender);
    function getSender() returns (address) {
        LogSender(msg.sender);
        return msg.sender;
    }
}

Jetzt in web3 würden Sie es wie nennen

// replace from with the account you want to send the tx from
const txHash = myContractInstance.getSender({ from: "xxxxxxxx" });
// once the tx has been mined, get the tx receipt
web3.eth.getTransactionReceipt(txHash, (err, receipt) => {
    console.log(receipt.logs[0].args.sender); // you will see sender address here
}

Wenn Sie nur den Ersteller des Vertrags erhalten möchten, ohne Benzin auszugeben, ist dies ziemlich einfach.

Sie erstellen eine Zustandsvariable mit dem Namen owner, machen sie öffentlich. Legen Sie die ownerim Konstruktor fest.

contract SimpleExample {
    address public owner;
    function SimpleExample() {
        owner = msg.sender;
    }
}

Solidity erstellt automatisch konstante Getter-Funktionen für öffentliche Zustandsvariablen. (Obwohl Sie es auch explizit tun können)

Denn die Vertragsspeicherung ist neben dem Bytecode auch für alle Beteiligten einsehbar. In web3 können Sie ownerähnliches erhalten

const ownerAddress = myContractInstance.owner()

Was in diesem Fall, da der Getter konstant ist, gleichbedeutend ist

const ownerAddress = myContractInstance.owner.call()
Ich habe die Funktion nicht konstant gemacht, und sie hat den msg.sender immer noch nicht zurückgegeben. Wie kann ich den msg.sender-Wert in einer Nicht-Transaktionsfunktion verwenden? Ich möchte Daten erhalten, ohne Benzin zu bezahlen, und ich möchte, dass diese Funktion nur dem Ersteller zugänglich ist. Wenn eine Nicht-Transaktionsfunktion den msg.sender-Wert nicht zurückgeben kann, wie kann sie ihn dann in der Funktionslogik verwenden?
Sie verwenden den Vertragsspeicher, um die Eigentümeradresse zu speichern
Ich möchte die Adresse des Eigentümers mit der Adresse des aktuellen Benutzers vergleichen. Wenn eine Nicht-Transaktionsfunktion den msg.sender-Wert nicht zurückgeben kann, wie kann sie ihn dann in der Logik der Funktion verwenden (um die Eigentümeradresse mit der Adresse des aktuellen Benutzers zu vergleichen)?
Kannst du nicht einfach tun myContractInstance.owner() === userAddress? Sie können Benutzerkonten in abrufen web3.eth.accounts.
Was ist die spezifische Vertragsmethode, die die Adresse der Person zurückgibt, die eine Nicht-Transaktionsfunktion aufgerufen hat? Dies muss innerhalb des Vertrags (nicht von JS) aus zugänglich sein, da die Logik dort mit der Adresse des Eigentümers verglichen werden muss.
Sie müssen nicht alles im Vertrag tun. Sie können es einfach web3.eth.accountsauf Ihrer Client-Seite überprüfen. Niemand kann feststellen, wer die Funktion außerhalb des Netzwerks aufgerufen hat. Tatsächlich benötigen Sie nicht einmal ein Konto, um die konstante Funktion aufzurufen