Ich würde gerne wissen, ob es möglich ist, die Adresse des Funktionsaufrufs des Nachrichtensenders des Vertrags beim Schreiben von Einheitentests in Solidität zu ändern. Es sollte wirklich so sein, ich habe versucht herauszufinden wie, konnte es aber nicht.
pragma solidity ^0.4.4;
import "truffle/Assert.sol";
import "truffle/DeployedAddresses.sol";
contract A {
event Test(address add);
function test() {
Test(msg.sender);
}
}
contract TestA {
function test01() {
A a = A(DeployedAddresses.A());
a.test(); // <--- msg.sender is address(this), but how do we use a different account from testrpc?
}
}
In Gitter habe ich eine Antwort bekommen, also habe ich versucht, es so auszuführen:
a.test({from: 0xf6a948bff792e4f42d7f17e5e4ebe20871d160f2});
Es gibt den folgenden Fehler:
TypeError: Wrong argument count for function call: 1 arguments given but expected 0. a.test({from: 0xf6a948bff792e4f42d7f17e5e4ebe20871d160f2});
Betriebssystem: Windows 10 Truffle-Version: v3.4.11 Ethereum-Client: testrpc v4.1.3 Knotenversion: v8.7.0 npm-Version: 5.4.2
Sie können die Absenderadresse nicht innerhalb von solidity ändern. Die Solidity-Tests werden innerhalb des EVM ausgeführt und erlauben keine Änderung des msg.sender. Es ist möglich, dass eine modifizierte Version des EVM eine solche Funktionalität bereitstellt, aber mir ist eine solche Modifikation nicht bekannt.
Sie können die zu testende Funktion ändern, um einen zusätzlichen Parameter zu akzeptieren, und dort den gewünschten Absender übergeben
contract A {
// We cannot test directly deposit
function deposit(uint _amount) public {
doDeposit(msg.sender, _amount);
}
// But we can test doDeposit
function doDeposit(address _sender) public {
}
}
contract TestA {
address constant senderA = "0xA00...";
address constant senderB = "0xB00...";
function testDeposit() {
A a = A(DeployedAddresses.A());
a.doDeposit(senderA, 10000);
a.doDeposit(senderB, 10000);
}
}
Es ist nicht ideal, aber es kann helfen, einige Fehler zu finden.
Eine weitere Möglichkeit ist die Verwendung der Testvertragsadresse
contract TestA {
address constant senderA = "0xA00...";
address constant senderB = "0xB00...";
function testMint() {
// TestA is the owner a
A a = new A(this);
// Only the owner TestA can mint
a.mint(senderA, 10000);
// make senderA approve TestA
a.doApprove(senderA, this, 1000);
// testA can make a transfer from senderA
a.transferFrom(senderA, senderB, 1000);
}
}
Da Sie einen Vertrag (TestA) haben, der eine Funktion eines anderen Vertrags (A) aufruft, ist msg.sender immer die Adresse von TestA in der Testfunktion von A, da für Vertrag A die Adresse, die die Nachricht gesendet hat, TestA war.
Wenn Sie die tatsächliche Adresse protokollieren möchten, die die Funktion ursprünglich aufgerufen hat, müssen Sie Folgendes tun:
pragma solidity ^0.4.4;
import "truffle/Assert.sol";
import "truffle/DeployedAddresses.sol";
contract A {
event Test(address add);
function test(address _sender) {
Test(_sender);
}
}
contract TestA {
function test01() {
A a = A(DeployedAddresses.A());
a.test(msg.sender);
}
}
Hier ist ein alternativer Ansatz, den ich effektiv zum Manipulieren msg.sender
in Unit-Tests verwendet habe, die in Solidität geschrieben sind:
SenderContract
und a implementieren ReceiverContract
, jeder hat seine eigene Adresse und wenn sie die CUT-Funktionen aufrufen, msg.sender
werden sie auf ihre bereitgestellten Adressen gesetztmsg.sender
hält die Adresse des Actor-Vertrags in diesen Aufrufen).
Marco Jakovic
Ismael
onlyTest
Modifikatoren haben, die nach einertest
Variablen suchen, aber es ist sehr hässlich.momoja
Ismael
momoja