Ich habe einen einfachen Vertrag, der hilft, eine Zahlung auf ein anderes Konto vorzunehmen. Nehmen wir an, ich beginne den Vertrag mit Wert V
, Vertragsgaskosten G
und Wert, der in das andere Konto umgerechnet wird X
. Ich gehe davon aus, dass folgendes zutreffen wird:
V = G + X
.
Es ist jedoch nicht.
Nach einem einfachen truffle init
Schritt arbeite ich mit dem folgenden Vertrag.
Pay.sol
pragma solidity ^0.4.17;
/// @title Pay - Facilitates payments.
contract Pay {
event Payment(
address _from,
address _to,
uint amount
);
/// @dev Makes a payment.
/// @param _to Address to pay to.
function pay(address _to) public payable {
require(msg.value > 0);
// Does this transfer the right amount of ether (msg.value measured in wei)?
_to.transfer(msg.value);
Payment(msg.sender, _to, msg.value);
}
}
Und die folgende Testdatei.
pay.js
var Pay = artifacts.require("./Pay.sol");
contract('Pay', function(accounts) {
it("should put money in the first account", function() {
return Pay.deployed().then(function(instance) {
pay = instance;
return web3.eth.getBalance(accounts[1]);
}).then(function(balance){
startingBalance = balance.toNumber();
gasPrice = 200000;
payAmount = 2500000;
return pay.pay(accounts[1], {from: accounts[0], value: payAmount, gasPrice: gasPrice });
}).then(function() {
return pay.pay.estimateGas(accounts[1], {from: accounts[0], value: payAmount });
}).then(function(gasCost) {
gasSpent = gasCost * gasPrice;
console.log(gasCost);
console.log(gasPrice);
console.log(gasSpent);
return web3.eth.getBalance(accounts[1]);
}).then(function(balance) {
endingBalance = balance.toNumber();
assert.equal(endingBalance - startingBalance, payAmount);
})
});
});
Die Ausgabe ist die folgende:
Contract: Pay
32001
200000
6400200000
1) should put money in the first account
Events emitted during test:
---------------------------
Payment(_from: 0x627306090abab3a6e1400e9345bc60c78a8bef57, _to: 0xf17f52151ebef6c7334fad080c5704d77216b732, amount: 2500000)
---------------------------
0 passing (476ms)
1 failing
1) Contract: Pay should put money in the first account:
AssertionError: expected 2506752 to equal 2500000
at test/pay.js:23:20
at <anonymous>
at process._tickCallback (internal/process/next_tick.js:118:7)
Insbesondere, wie Sie der Ausgabe entnehmen können:
V-X=-6752
(kann es auch negativ sein?)G=6400200000
UPDATE : Richtige Antwort als Referenz.
pay.js
var Pay = artifacts.require("./Pay.sol");
contract('Pay', function(accounts) {
it("should put money in the first account", function() {
return Pay.deployed().then(function(instance) {
pay = instance;
return web3.eth.getBalance(accounts[1]);
}).then(function(balance){
startingBalance = balance;
gasPrice = 200000;
payAmount = 2500000;
return pay.pay(accounts[1], {from: accounts[0], value: payAmount, gasPrice: gasPrice });
}).then(function(result) {
gasUsed = result.receipt.gasUsed;
return pay.pay.estimateGas(accounts[1], {from: accounts[0], value: payAmount });
}).then(function(gasCost) {
gasSpent = gasCost * gasPrice;
return web3.eth.getBalance(accounts[1]);
}).then(function(balance) {
endingBalance = balance;
assert.equal(endingBalance.sub(startingBalance).toNumber(), payAmount);
})
});
it("should pay gas costs from the second account", function() {
return Pay.deployed().then(function(instance) {
pay = instance;
return web3.eth.getBalance(accounts[0]);
}).then(function(balance){
startingBalance = balance;
gasPrice = 200000;
payAmount = 2500000;
return pay.pay(accounts[1], {from: accounts[0], value: payAmount, gasPrice: gasPrice });
}).then(function(result) {
gasUsed = result.receipt.gasUsed;
return pay.pay.estimateGas(accounts[1], {from: accounts[0], value: payAmount });
}).then(function(gasCost) {
gasSpent = gasCost * gasPrice;
return web3.eth.getBalance(accounts[0]);
}).then(function(balance) {
endingBalance = balance;
assert.equal(startingBalance.sub(endingBalance).toNumber(), payAmount + gasSpent);
})
});
});
Sie nehmen die Differenz mit den Zahlen von Javascript
startingBalance = balance.toNumber();
...
endingBalance = balance.toNumber();
assert.equal(endingBalance - startingBalance, payAmount);
Aber JavaScript-Zahlen haben nicht genug Genauigkeit, um große Werte zu verarbeiten.
Sie sollten das Guthaben als BigNums speichern und die Umwandlung in Zahlen als letzte Operation vornehmen.
startingBalance = balance;
...
endingBalance = balance;
assert.equal(endingBalance.sub(startingBalance).toNumber(), payAmount);
Auch Sie bezahlen die Operationen, mit account[0]
denen Sie Guthaben von diesem Konto verwenden müssen, um das verbrauchte Gas zu messen.
Verwenden Sie estimateGas
zur Bestimmung des Verbrauchsgases das gasUsed
Feld aus dem Beleg der Transaktion .
Aus der eth_estimategas- Dokumentation
Beachten Sie, dass die Schätzung aus verschiedenen Gründen, einschließlich der EVM-Mechanik und der Knotenleistung, erheblich höher sein kann als die tatsächlich von der Transaktion verbrauchte Gasmenge.
Es gibt Vorgänge, die negative Kosten verursachen, zum Beispiel wird das Löschen des Speichers Gas zurückgeben, aber es muss zuerst erfolgreich sein.
Peter ist
result.receipt
bekomme ich einen Gasverbrauch von 32001 was der obigen Schätzung entspricht. Allerdings muss ich das mit dem von mir eingestellten gasPrice von 200.000 multiplizieren. Die sich daraus ergebende Gesamtgasgebühr von 6.400.200.000 stimmt nicht mit dem aus dem Vertrag gezahlten zusätzlichen Betrag überein.Ismael