Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EVM: Shift transferdomain transparent tx into the correct attribute #2447

Merged
merged 3 commits into from
Sep 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 42 additions & 41 deletions src/masternodes/consensus/xvm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -192,29 +192,30 @@ Res CXVMConsensus::operator()(const CTransferDomainMessage &obj) const {
// Iterate over array of transfers
for (const auto &[src, dst] : obj.transfers) {
CrossBoundaryResult result;
auto hash = evm_try_get_tx_hash(result, HexStr(dst.data));
if (!result.ok) {
return Res::Err("Error bridging DFI: %s", result.reason);
}
evmTxHash = std::string(hash.data(), hash.length()).substr(2);

if (src.domain == static_cast<uint8_t>(VMDomain::DVM) && dst.domain == static_cast<uint8_t>(VMDomain::EVM)) {
// Check if destination address is a contract
{
CTxDestination dest;
ExtractDestination(dst.address, dest);
const auto toAddress = std::get<WitnessV16EthHash>(dest);
CTxDestination dest;
if (!ExtractDestination(dst.address, dest)) {
return DeFiErrors::TransferDomainETHDestAddress();
}
const auto toAddress = std::get_if<WitnessV16EthHash>(&dest);
if (!toAddress) {
return DeFiErrors::TransferDomainETHSourceAddress();
}

CrossBoundaryResult result;
auto isSmartContract = evm_is_smart_contract_in_q(result, toAddress.GetHex(), evmQueueId);
// Check if destination address is a contract
auto isSmartContract = evm_is_smart_contract_in_q(result, toAddress->GetHex(), evmQueueId);
if (!result.ok) {
return Res::Err("Error checking contract address: %s", result.reason);
}
if (isSmartContract) {
return DeFiErrors::TransferDomainSmartContractDestAddress();
}

if (!result.ok) {
return Res::Err("transferdomain error: %s", result.reason);
}
if (isSmartContract) {
return Res::Err("transferdomain error: EVM destination is a smart contract");
}
auto hash = evm_try_get_tx_hash(result, HexStr(dst.data));
if (!result.ok) {
return Res::Err("Error bridging DFI: %s", result.reason);
}
evmTxHash = std::string(hash.data(), hash.length()).substr(2);

// Subtract balance from DFI address
res = mnview.SubBalance(src.address, src.amount);
Expand All @@ -225,9 +226,6 @@ Res CXVMConsensus::operator()(const CTransferDomainMessage &obj) const {
stats.dvmCurrent.Sub(src.amount);

// Add balance to ERC55 address
CTxDestination dest;
ExtractDestination(dst.address, dest);

auto tokenId = dst.amount.nTokenId;
if (tokenId == DCT_ID{0}) {
evm_unsafe_try_add_balance_in_q(result, evmQueueId, HexStr(dst.data), tx.GetHash().GetHex());
Expand All @@ -245,39 +243,42 @@ Res CXVMConsensus::operator()(const CTransferDomainMessage &obj) const {
stats.evmIn.Add(tokenAmount);
stats.evmCurrent.Add(tokenAmount);
} else if (src.domain == static_cast<uint8_t>(VMDomain::EVM) && dst.domain == static_cast<uint8_t>(VMDomain::DVM)) {
// Check if source address is a contract
{
CTxDestination dest;
ExtractDestination(src.address, dest);
const auto fromAddress = std::get<WitnessV16EthHash>(dest);
CTxDestination dest;
if (!ExtractDestination(src.address, dest)) {
return DeFiErrors::TransferDomainETHSourceAddress();
}
const auto fromAddress = std::get_if<WitnessV16EthHash>(&dest);
if (!fromAddress) {
return DeFiErrors::TransferDomainETHSourceAddress();
}

CrossBoundaryResult result;
auto isSmartContract = evm_is_smart_contract_in_q(result, fromAddress.GetHex(), evmQueueId);
// Check if source address is a contract
auto isSmartContract = evm_is_smart_contract_in_q(result, fromAddress->GetHex(), evmQueueId);
if (!result.ok) {
return Res::Err("Error checking contract address: %s", result.reason);
}
if (isSmartContract) {
return DeFiErrors::TransferDomainSmartContractSourceAddress();
}

if (!result.ok) {
return Res::Err("transferdomain error: %s", result.reason);
}
if (isSmartContract) {
return Res::Err("transferdomain error: EVM source is a smart contract");
}
auto hash = evm_try_get_tx_hash(result, HexStr(src.data));
if (!result.ok) {
return Res::Err("Error bridging DFI: %s", result.reason);
}
evmTxHash = std::string(hash.data(), hash.length()).substr(2);

// Subtract balance from ERC55 address
CTxDestination dest;
ExtractDestination(src.address, dest);

auto tokenId = dst.amount.nTokenId;
CrossBoundaryResult result;
if (tokenId == DCT_ID{0}) {
if (!evm_unsafe_try_sub_balance_in_q(result, evmQueueId, HexStr(dst.data), tx.GetHash().GetHex())) {
if (!evm_unsafe_try_sub_balance_in_q(result, evmQueueId, HexStr(src.data), tx.GetHash().GetHex())) {
return DeFiErrors::TransferDomainNotEnoughBalance(EncodeDestination(dest));
}
if (!result.ok) {
return Res::Err("Error bridging DFI: %s", result.reason);
}
}
else {
evm_try_bridge_dst20(result, evmQueueId, HexStr(dst.data), tx.GetHash().GetHex(), tokenId.v, false);
evm_try_bridge_dst20(result, evmQueueId, HexStr(src.data), tx.GetHash().GetHex(), tokenId.v, false);
if (!result.ok) {
return Res::Err("Error bridging DST20: %s", result.reason);
}
Expand Down
8 changes: 8 additions & 0 deletions src/masternodes/errors.h
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,14 @@ class DeFiErrors {
return Res::Err("TransferDomain currently only supports a single transfer per transaction");
}

static Res TransferDomainSmartContractSourceAddress() {
return Res::Err("TransferDomain EVM source is a smart contract");
}

static Res TransferDomainSmartContractDestAddress() {
return Res::Err("TransferDomain EVM destination is a smart contract");
}

static Res SettingEVMAttributeFailure() {
return Res::Err("Failed to set EVM attribute");
}
Expand Down
6 changes: 5 additions & 1 deletion src/masternodes/rpc_accounts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2153,7 +2153,11 @@ UniValue transferdomain(const JSONRPCRequest& request) {

std::vector<uint8_t> evmTx(signedTx.size());
std::copy(signedTx.begin(), signedTx.end(), evmTx.begin());
dst.data = evmTx;
if (isEVMIn) {
dst.data = evmTx;
} else {
src.data = evmTx;
}

msg.transfers.push_back({src, dst});
}
Expand Down
10 changes: 9 additions & 1 deletion src/miner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -630,7 +630,15 @@ bool BlockAssembler::EvmTxPreapply(const EvmTxPreApplyContext& ctx)
if (obj.transfers.size() != 1) {
return false;
}
auto senderInfo = evm_try_get_tx_sender_info_from_raw_tx(result, HexStr(obj.transfers[0].second.data));

std::string evmTx = "";
if (obj.transfers[0].first.domain == static_cast<uint8_t>(VMDomain::DVM) && obj.transfers[0].second.domain == static_cast<uint8_t>(VMDomain::EVM)) {
evmTx = HexStr(obj.transfers[0].second.data);
}
else if (obj.transfers[0].first.domain == static_cast<uint8_t>(VMDomain::EVM) && obj.transfers[0].second.domain == static_cast<uint8_t>(VMDomain::DVM)) {
evmTx = HexStr(obj.transfers[0].first.data);
}
auto senderInfo = evm_try_get_tx_sender_info_from_raw_tx(result, evmTx);
if (!result.ok) {
return false;
}
Expand Down
10 changes: 9 additions & 1 deletion src/txmempool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1304,7 +1304,15 @@ Res CTxMemPool::rebuildAccountsView(int height, const CCoinsViewCache& coinsCach
}
continue;
}
auto senderInfo = evm_try_get_tx_sender_info_from_raw_tx(result, HexStr(obj.transfers[0].second.data));

std::string evmTx = "";
if (obj.transfers[0].first.domain == static_cast<uint8_t>(VMDomain::DVM) && obj.transfers[0].second.domain == static_cast<uint8_t>(VMDomain::EVM)) {
evmTx = HexStr(obj.transfers[0].second.data);
}
else if (obj.transfers[0].first.domain == static_cast<uint8_t>(VMDomain::EVM) && obj.transfers[0].second.domain == static_cast<uint8_t>(VMDomain::DVM)) {
evmTx = HexStr(obj.transfers[0].first.data);
}
auto senderInfo = evm_try_get_tx_sender_info_from_raw_tx(result, evmTx);
if (!result.ok) {
if (newTxLoop) {
newEntryRes = Res::Err(result.reason.c_str());
Expand Down
5 changes: 3 additions & 2 deletions test/functional/feature_evm_transferdomain.py
Original file line number Diff line number Diff line change
Expand Up @@ -736,7 +736,6 @@ def invalid_transfer_sc(self):
tx, self.evm_key_pair.privkey
)
hash = self.nodes[0].w3.eth.send_raw_transaction(signed.rawTransaction)

self.nodes[0].generate(1)

receipt = self.nodes[0].w3.eth.wait_for_transaction_receipt(hash)
Expand Down Expand Up @@ -776,7 +775,9 @@ def invalid_transfer_sc_mempool(self):
"gas": 1_000_000,
}
)
signed = self.nodes[0].w3.eth.account.sign_transaction(tx, self.evm_key_pair.privkey)
signed = self.nodes[0].w3.eth.account.sign_transaction(
tx, self.evm_key_pair.privkey
)
self.nodes[0].w3.eth.send_raw_transaction(signed.rawTransaction)

contract_address = web3.utils.get_create_address(
Expand Down