|
@ -194,7 +194,7 @@ QVariantMap ClientModel::contractAddresses() const |
|
|
{ |
|
|
{ |
|
|
QVariantMap res; |
|
|
QVariantMap res; |
|
|
for (auto const& c: m_contractAddresses) |
|
|
for (auto const& c: m_contractAddresses) |
|
|
res.insert(c.first, QString::fromStdString(toJS(c.second))); |
|
|
res.insert(c.first.first, QString::fromStdString(toJS(c.second))); |
|
|
return res; |
|
|
return res; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -256,7 +256,9 @@ void ClientModel::setupState(QVariantMap _state) |
|
|
u256 value = (qvariant_cast<QEther*>(transaction.value("value")))->toU256Wei(); |
|
|
u256 value = (qvariant_cast<QEther*>(transaction.value("value")))->toU256Wei(); |
|
|
u256 gasPrice = (qvariant_cast<QEther*>(transaction.value("gasPrice")))->toU256Wei(); |
|
|
u256 gasPrice = (qvariant_cast<QEther*>(transaction.value("gasPrice")))->toU256Wei(); |
|
|
QString sender = transaction.value("sender").toString(); |
|
|
QString sender = transaction.value("sender").toString(); |
|
|
bool isStdContract = (transaction.value("stdContract").toBool()); |
|
|
bool isStdContract = transaction.value("stdContract").toBool(); |
|
|
|
|
|
bool isContractCreation = transaction.value("isContractCreation").toBool(); |
|
|
|
|
|
bool isFunctionCall = transaction.value("isFunctionCall").toBool(); |
|
|
if (isStdContract) |
|
|
if (isStdContract) |
|
|
{ |
|
|
{ |
|
|
if (contractId.isEmpty()) //TODO: This is to support old project files, remove later
|
|
|
if (contractId.isEmpty()) //TODO: This is to support old project files, remove later
|
|
@ -272,7 +274,7 @@ void ClientModel::setupState(QVariantMap _state) |
|
|
{ |
|
|
{ |
|
|
if (contractId.isEmpty() && m_codeModel->hasContract()) //TODO: This is to support old project files, remove later
|
|
|
if (contractId.isEmpty() && m_codeModel->hasContract()) //TODO: This is to support old project files, remove later
|
|
|
contractId = m_codeModel->contracts().keys()[0]; |
|
|
contractId = m_codeModel->contracts().keys()[0]; |
|
|
TransactionSettings transactionSettings(contractId, functionId, value, gas, gasAuto, gasPrice, Secret(sender.toStdString())); |
|
|
TransactionSettings transactionSettings(contractId, functionId, value, gas, gasAuto, gasPrice, Secret(sender.toStdString()), isContractCreation, isFunctionCall); |
|
|
transactionSettings.parameterValues = transaction.value("parameters").toMap(); |
|
|
transactionSettings.parameterValues = transaction.value("parameters").toMap(); |
|
|
|
|
|
|
|
|
if (contractId == functionId || functionId == "Constructor") |
|
|
if (contractId == functionId || functionId == "Constructor") |
|
@ -308,6 +310,14 @@ void ClientModel::executeSequence(vector<TransactionSettings> const& _sequence, |
|
|
m_gasCosts.clear(); |
|
|
m_gasCosts.clear(); |
|
|
for (TransactionSettings const& transaction: _sequence) |
|
|
for (TransactionSettings const& transaction: _sequence) |
|
|
{ |
|
|
{ |
|
|
|
|
|
std::pair<QString, int> ctrInstance = resolvePair(transaction.contractId); |
|
|
|
|
|
QString address = resolveToken(ctrInstance, deployedContracts); |
|
|
|
|
|
if (!transaction.isFunctionCall) |
|
|
|
|
|
{ |
|
|
|
|
|
callAddress(Address(address.toStdString()), bytes(), transaction); |
|
|
|
|
|
onNewTransaction(); |
|
|
|
|
|
continue; |
|
|
|
|
|
} |
|
|
ContractCallDataEncoder encoder; |
|
|
ContractCallDataEncoder encoder; |
|
|
if (!transaction.stdContractUrl.isEmpty()) |
|
|
if (!transaction.stdContractUrl.isEmpty()) |
|
|
{ |
|
|
{ |
|
@ -322,7 +332,7 @@ void ClientModel::executeSequence(vector<TransactionSettings> const& _sequence, |
|
|
else |
|
|
else |
|
|
{ |
|
|
{ |
|
|
//encode data
|
|
|
//encode data
|
|
|
CompiledContract const& compilerRes = m_codeModel->contract(transaction.contractId); |
|
|
CompiledContract const& compilerRes = m_codeModel->contract(ctrInstance.first); |
|
|
QFunctionDefinition const* f = nullptr; |
|
|
QFunctionDefinition const* f = nullptr; |
|
|
bytes contractCode = compilerRes.bytes(); |
|
|
bytes contractCode = compilerRes.bytes(); |
|
|
shared_ptr<QContractDefinition> contractDef = compilerRes.sharedContract(); |
|
|
shared_ptr<QContractDefinition> contractDef = compilerRes.sharedContract(); |
|
@ -348,32 +358,29 @@ void ClientModel::executeSequence(vector<TransactionSettings> const& _sequence, |
|
|
{ |
|
|
{ |
|
|
QSolidityType const* type = p->type(); |
|
|
QSolidityType const* type = p->type(); |
|
|
QVariant value = transaction.parameterValues.value(p->name()); |
|
|
QVariant value = transaction.parameterValues.value(p->name()); |
|
|
if (type->type().type == SolidityType::Type::Address && value.toString().startsWith("<") && value.toString().endsWith(">")) |
|
|
if (type->type().type == SolidityType::Type::Address) |
|
|
{ |
|
|
{ |
|
|
QStringList nb = value.toString().remove("<").remove(">").split(" - "); |
|
|
std::pair<QString, int> ctrParamInstance = resolvePair(value.toString()); |
|
|
value = QVariant(QString::fromStdString("0x" + dev::toHex(deployedContracts.at(nb.back().toInt()).ref()))); |
|
|
value = QVariant(resolveToken(ctrParamInstance, deployedContracts)); |
|
|
} |
|
|
} |
|
|
encoder.encode(value, type->type()); |
|
|
encoder.encode(value, type->type()); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if (transaction.functionId.isEmpty() || transaction.functionId == transaction.contractId) |
|
|
if (transaction.functionId.isEmpty() || transaction.functionId == ctrInstance.first) |
|
|
{ |
|
|
{ |
|
|
bytes param = encoder.encodedData(); |
|
|
bytes param = encoder.encodedData(); |
|
|
contractCode.insert(contractCode.end(), param.begin(), param.end()); |
|
|
contractCode.insert(contractCode.end(), param.begin(), param.end()); |
|
|
Address newAddress = deployContract(contractCode, transaction); |
|
|
Address newAddress = deployContract(contractCode, transaction); |
|
|
deployedContracts.push_back(newAddress); |
|
|
deployedContracts.push_back(newAddress); |
|
|
auto contractAddressIter = m_contractAddresses.find(transaction.contractId); |
|
|
std::pair<QString, int> contractToken = retrieveToken(transaction.contractId, deployedContracts); |
|
|
if (contractAddressIter == m_contractAddresses.end() || newAddress != contractAddressIter->second) |
|
|
m_contractAddresses[contractToken] = newAddress; |
|
|
{ |
|
|
m_contractNames[newAddress] = contractToken.first; |
|
|
m_contractAddresses[transaction.contractId] = newAddress; |
|
|
contractAddressesChanged(); |
|
|
m_contractNames[newAddress] = transaction.contractId; |
|
|
|
|
|
contractAddressesChanged(); |
|
|
|
|
|
} |
|
|
|
|
|
gasCostsChanged(); |
|
|
gasCostsChanged(); |
|
|
} |
|
|
} |
|
|
else |
|
|
else |
|
|
{ |
|
|
{ |
|
|
auto contractAddressIter = m_contractAddresses.find(transaction.contractId); |
|
|
auto contractAddressIter = m_contractAddresses.find(ctrInstance); |
|
|
if (contractAddressIter == m_contractAddresses.end()) |
|
|
if (contractAddressIter == m_contractAddresses.end()) |
|
|
{ |
|
|
{ |
|
|
emit runFailed("Contract '" + transaction.contractId + tr(" not deployed.") + "' " + tr(" Cannot call ") + transaction.functionId); |
|
|
emit runFailed("Contract '" + transaction.contractId + tr(" not deployed.") + "' " + tr(" Cannot call ") + transaction.functionId); |
|
@ -381,7 +388,7 @@ void ClientModel::executeSequence(vector<TransactionSettings> const& _sequence, |
|
|
emit runStateChanged(); |
|
|
emit runStateChanged(); |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
callContract(contractAddressIter->second, encoder.encodedData(), transaction); |
|
|
callAddress(contractAddressIter->second, encoder.encodedData(), transaction); |
|
|
} |
|
|
} |
|
|
m_gasCosts.append(m_client->lastExecution().gasUsed); |
|
|
m_gasCosts.append(m_client->lastExecution().gasUsed); |
|
|
} |
|
|
} |
|
@ -405,6 +412,37 @@ void ClientModel::executeSequence(vector<TransactionSettings> const& _sequence, |
|
|
}); |
|
|
}); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::pair<QString, int> ClientModel::resolvePair(QString const& _contractId) |
|
|
|
|
|
{ |
|
|
|
|
|
std::pair<QString, int> ret; |
|
|
|
|
|
ret.first = _contractId; |
|
|
|
|
|
ret.second = -1; |
|
|
|
|
|
if (_contractId.startsWith("<") && _contractId.endsWith(">")) |
|
|
|
|
|
{ |
|
|
|
|
|
QStringList values = ret.first.remove("<").remove(">").split(" - "); |
|
|
|
|
|
ret.first = values[0]; |
|
|
|
|
|
ret.second = values[1].toUInt(); |
|
|
|
|
|
} |
|
|
|
|
|
return ret; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
QString ClientModel::resolveToken(std::pair<QString, int> const& _value, vector<Address> const& _contracts) |
|
|
|
|
|
{ |
|
|
|
|
|
if (_value.second != -1) |
|
|
|
|
|
return QString::fromStdString("0x" + dev::toHex(_contracts.at(_value.second).ref())); |
|
|
|
|
|
else |
|
|
|
|
|
return _value.first; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
std::pair<QString, int> ClientModel::retrieveToken(QString const& _value, vector<Address> const& _contracts) |
|
|
|
|
|
{ |
|
|
|
|
|
std::pair<QString, int> ret; |
|
|
|
|
|
ret.first = _value; |
|
|
|
|
|
ret.second = _contracts.size() - 1; |
|
|
|
|
|
return ret; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
void ClientModel::showDebugger() |
|
|
void ClientModel::showDebugger() |
|
|
{ |
|
|
{ |
|
|
ExecutionResult last = m_client->lastExecution(); |
|
|
ExecutionResult last = m_client->lastExecution(); |
|
@ -609,7 +647,7 @@ Address ClientModel::deployContract(bytes const& _code, TransactionSettings cons |
|
|
return newAddress; |
|
|
return newAddress; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void ClientModel::callContract(Address const& _contract, bytes const& _data, TransactionSettings const& _tr) |
|
|
void ClientModel::callAddress(Address const& _contract, bytes const& _data, TransactionSettings const& _tr) |
|
|
{ |
|
|
{ |
|
|
m_client->submitTransaction(_tr.sender, _tr.value, _contract, _data, _tr.gas, _tr.gasPrice, _tr.gasAuto); |
|
|
m_client->submitTransaction(_tr.sender, _tr.value, _contract, _data, _tr.gas, _tr.gasPrice, _tr.gasAuto); |
|
|
} |
|
|
} |
|
|