diff --git a/mix/ClientModel.cpp b/mix/ClientModel.cpp index 238fa5372..cad210f1b 100644 --- a/mix/ClientModel.cpp +++ b/mix/ClientModel.cpp @@ -331,7 +331,7 @@ void ClientModel::executeSequence(vector const& _sequence, { QSolidityType const* type = p->type(); QVariant value = transaction.parameterValues.value(p->name()); - if (type->type().type == SolidityType::Type::Address) + if (type->type().type == SolidityType::Type::Address && value.toString().startsWith("<")) { std::pair ctrParamInstance = resolvePair(value.toString()); value = QVariant(resolveToken(ctrParamInstance, deployedContracts)); diff --git a/mix/CodeModel.cpp b/mix/CodeModel.cpp index 2b4e332c0..de1bb8647 100644 --- a/mix/CodeModel.cpp +++ b/mix/CodeModel.cpp @@ -380,7 +380,23 @@ void CodeModel::gasEstimation(solidity::CompilerStack const& _cs) GasMeter::GasConsumption cost = gasItem->second; std::stringstream v; v << cost.value; - m_gasCostsMaps->push(sourceName, location.start, location.end, QString::fromStdString(v.str()), cost.isInfinite); + m_gasCostsMaps->push(sourceName, location.start, location.end, QString::fromStdString(v.str()), cost.isInfinite, "statement"); + } + + if (contractDefinition.getConstructor() != nullptr) + { + GasMeter::GasConsumption cost = GasEstimator::functionalEstimation(*_cs.getRuntimeAssemblyItems(n), contractDefinition.getConstructor()->externalSignature()); + std::stringstream v; + v << cost.value; + m_gasCostsMaps->push(sourceName, contractDefinition.getConstructor()->getLocation().start, contractDefinition.getConstructor()->getLocation().end, QString::fromStdString(v.str()), cost.isInfinite, "constructor"); + } + + for (auto func: contractDefinition.getDefinedFunctions()) + { + GasMeter::GasConsumption cost = GasEstimator::functionalEstimation(*_cs.getRuntimeAssemblyItems(n), func->externalSignature()); + std::stringstream v; + v << cost.value; + m_gasCostsMaps->push(sourceName, func->getLocation().start, func->getLocation().end, QString::fromStdString(v.str()), cost.isInfinite, "function"); } } } @@ -583,9 +599,9 @@ QString CodeModel::resolveFunctionName(dev::SourceLocation const& _location) return QString(); } -void GasMapWrapper::push(QString _source, int _start, int _end, QString _value, bool _isInfinite) +void GasMapWrapper::push(QString _source, int _start, int _end, QString _value, bool _isInfinite, QString _payload) { - GasMap* gas = new GasMap(_start, _end, _value, _isInfinite, this); + GasMap* gas = new GasMap(_start, _end, _value, _isInfinite, _payload, this); m_gasMaps.find(_source).value().push_back(QVariant::fromValue(gas)); } diff --git a/mix/CodeModel.h b/mix/CodeModel.h index dcf3d0c1e..5982982b3 100644 --- a/mix/CodeModel.h +++ b/mix/CodeModel.h @@ -138,7 +138,7 @@ class GasMapWrapper: public QObject public: GasMapWrapper(QObject* _parent = nullptr): QObject(_parent){} - void push(QString _source, int _start, int _end, QString _value, bool _isInfinite); + void push(QString _source, int _start, int _end, QString _value, bool _isInfinite, QString _payload); bool contains(QString _key); void insert(QString _source, QVariantList _variantList); QVariantList gasCostsByDocId(QString _source); @@ -155,14 +155,16 @@ class GasMap: public QObject Q_PROPERTY(int end MEMBER m_end CONSTANT) Q_PROPERTY(QString gas MEMBER m_gas CONSTANT) Q_PROPERTY(bool isInfinite MEMBER m_isInfinite CONSTANT) + Q_PROPERTY(QString payload MEMBER m_payload CONSTANT) public: - GasMap(int _start, int _end, QString _gas, bool _isInfinite, QObject* _parent): QObject(_parent), m_start(_start), m_end(_end), m_gas(_gas), m_isInfinite(_isInfinite) {} + GasMap(int _start, int _end, QString _gas, bool _isInfinite, QString _payload, QObject* _parent): QObject(_parent), m_start(_start), m_end(_end), m_gas(_gas), m_isInfinite(_isInfinite), m_payload(_payload) {} int m_start; int m_end; QString m_gas; bool m_isInfinite; + QString m_payload; }; /// Code compilation model. Compiles contracts in background an provides compiled contract data diff --git a/mix/qml/html/cm/inkpot.css b/mix/qml/html/cm/inkpot.css index 6a2d8d63a..b31e20ad8 100644 --- a/mix/qml/html/cm/inkpot.css +++ b/mix/qml/html/cm/inkpot.css @@ -68,3 +68,11 @@ span.CodeMirror-selectedtext { color: #ffffff !important; } font-size: 12px; } +.CodeMirror-gasCost +{ + font-family: monospace; + font-size: 14px; + color: #409090; + text-shadow: none !important; + margin-left: 5px; +} diff --git a/mix/qml/html/codeeditor.js b/mix/qml/html/codeeditor.js index 6af8ff131..151eb2c29 100644 --- a/mix/qml/html/codeeditor.js +++ b/mix/qml/html/codeeditor.js @@ -210,9 +210,9 @@ setFontSize = function(size) makeGasCostMarker = function(value) { var marker = document.createElement("div"); - marker.style.color = "#822"; + //marker.style.color = "#822"; marker.innerHTML = value; - marker.className = "CodeMirror-errorannotation-context"; + marker.className = "CodeMirror-gasCost"; return marker; }; @@ -252,8 +252,23 @@ displayGasEstimation = function(show) else color = colorGradient[colorIndex]; var className = "CodeMirror-gasCosts" + i; - var line = editor.posFromIndex(gasCosts[i].start) - gasMarkText.push(editor.markText(line, editor.posFromIndex(gasCosts[i].end), { inclusiveLeft: true, inclusiveRight: true, handleMouseEvents: true, className: className, css: "background-color:" + color })); + var line = editor.posFromIndex(gasCosts[i].start); + var endChar; + if (gasCosts[i].payload === "statement") + { + endChar = editor.posFromIndex(gasCosts[i].end); + gasMarkText.push({ line: line, markText: editor.markText(line, endChar, { inclusiveLeft: true, inclusiveRight: true, handleMouseEvents: true, className: className, css: "background-color:" + color })}); + } + else if (gasCosts[i].payload === "function" || gasCosts[i].payload === "constructor") + { + var l = editor.getLine(line.line); + endChar = { line: line.line, ch: line.ch + l.length }; + var marker = document.createElement("div"); + marker.innerHTML = " max execution cost: " + gasCosts[i].gas + " gas"; + marker.className = "CodeMirror-gasCost"; + editor.addWidget(endChar, marker, false, "over"); + gasMarkText.push({ line: line.line, widget: marker }); + } gasMarkRef[className] = { line: line.line, value: gasCosts[i] }; } } @@ -275,7 +290,12 @@ function clearGasMark() { if (gasMarkText) for (var k in gasMarkText) - gasMarkText[k].clear(); + { + if (gasMarkText[k] && gasMarkText[k].markText) + gasMarkText[k].markText.clear(); + if (gasMarkText[k] && gasMarkText[k].widget) + gasMarkText[k].widget.remove(); + } } var gasAnnotation; @@ -290,7 +310,7 @@ function listenMouseOver(e) gasAnnotation.clear(); var cl = getGasCostClass(node); var gasTitle = gasMarkRef[cl].value.isInfinite ? "infinite" : gasMarkRef[cl].value.gas; - gasTitle = gasTitle + " gas"; + gasTitle = " execution cost: " + gasTitle + " gas"; gasAnnotation = editor.addLineWidget(gasMarkRef[cl].line + 1, makeGasCostMarker(gasTitle), { coverGutter: false, above: true }); } else if (gasAnnotation)