Skip to content

Commit

Permalink
EVM in/out refinements (#1868)
Browse files Browse the repository at this point in the history
* Return error on sub balance failure.

* Change to expected return type

* Update EVM in/out TX

* Use array instead of rust::Vec

* Pass context to CustomTxVisit

* Add temporary state to TransactionQueue

* Improve readability

* Block integration test

---------

Co-authored-by: Bushstar <[email protected]>
  • Loading branch information
2 people authored and canonbrother committed Apr 10, 2023
1 parent f4de29d commit 326c823
Show file tree
Hide file tree
Showing 10 changed files with 425 additions and 289 deletions.
2 changes: 2 additions & 0 deletions src/amount.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ struct DCT_ID {

static constexpr CAmount COIN = 100000000;
static constexpr CAmount CENT = 1000000;
static constexpr int64_t WEI_IN_GWEI = 1000000000;
static constexpr int64_t CAMOUNT_TO_WEI = 10;

//Converts the given value to decimal format string with COIN precision.
inline std::string GetDecimalString(CAmount nValue)
Expand Down
52 changes: 41 additions & 11 deletions src/masternodes/mn_checks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3834,12 +3834,6 @@ class CCustomTxApplyVisitor : public CCustomTxVisitor {
const auto sumFrom = SumAllTransfers(obj.from);
const auto sumTo = SumAllTransfers(obj.to);

if (obj.type == CTransferBalanceType::EvmIn || obj.type == CTransferBalanceType::EvmOut) {
for (const auto& [id, _] : sumFrom.balances)
if (id != DCT_ID{0})
return Res::Err("For EVM in/out transfers only DFI token is currently supported");
}

if (sumFrom != sumTo)
return Res::Err("sum of inputs (from) != sum of outputs (to)");

Expand All @@ -3851,18 +3845,54 @@ class CCustomTxApplyVisitor : public CCustomTxVisitor {
if (!res)
return res;
} else if (obj.type == CTransferBalanceType::EvmIn) {
for (const auto& [addr, _] : obj.to) {
res = SubBalancesDelShares(obj.from);
if (!res)
return res;

for (const auto& [addr, balances] : obj.to) {
CTxDestination dest;
if (ExtractDestination(addr, dest)) {
if (dest.index() != WitV16KeyEthHashType) {
return Res::Err("To address must be an ETH address in case of \"evmin\" transfertype");
}
}

const auto toAddress = std::get<WitnessV16EthHash>(dest);

for (const auto& [id, amount] : balances.balances) {
if (id != DCT_ID{0}) {
return Res::Err("For EVM out transfers, only DFI token is currently supported");
}

arith_uint256 balanceIn = amount;
balanceIn *= CAMOUNT_TO_WEI * WEI_IN_GWEI;
evm_add_balance(evmContext, HexStr(toAddress.begin(), toAddress.end()), ArithToUint256(balanceIn).ToArrayReversed());
}
}
res = SubBalancesDelShares(obj.from);
if (!res)
return res;
} else if (obj.type == CTransferBalanceType::EvmOut) {
for (const auto& [addr, balances] : obj.from) {
CTxDestination dest;
if (ExtractDestination(addr, dest)) {
if (dest.index() != WitV16KeyEthHashType) {
return Res::Err("Invalid destination");
}
}

const auto fromAddress = std::get<WitnessV16EthHash>(dest);

for (const auto& [id, amount] : balances.balances) {
if (id != DCT_ID{0}) {
return Res::Err("For EVM out transfers, only DFI token is currently supported");
}

arith_uint256 balanceIn = amount;
balanceIn *= CAMOUNT_TO_WEI * WEI_IN_GWEI;
if (!evm_sub_balance(evmContext, HexStr(fromAddress.begin(), fromAddress.end()), ArithToUint256(balanceIn).ToArrayReversed())) {
return Res::Err("Not enough balance in %s to cover EVM out", EncodeDestination(dest));
}
}
}

res = AddBalancesSetShares(obj.to);
if (!res)
return res;
Expand Down Expand Up @@ -4085,7 +4115,7 @@ Res ApplyCustomTx(CCustomCSView &mnview,
PopulateVaultHistoryData(mnview.GetHistoryWriters(), view, txMessage, txType, height, txn, tx.GetHash());
}

res = CustomTxVisit(view, coins, tx, height, consensus, txMessage, time, txn);
res = CustomTxVisit(view, coins, tx, height, consensus, txMessage, time, txn, evmContext);

if (res) {
if (canSpend && txType == CustomTxType::UpdateMasternode) {
Expand Down
3 changes: 0 additions & 3 deletions src/masternodes/rpc_evm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@
#include <libain_evm.h>
#include <key_io.h>

const int64_t WEI_IN_GWEI = 1000000000;
const int64_t CAMOUNT_TO_WEI = 10;

UniValue evmtx(const JSONRPCRequest& request) {
auto pwallet = GetWallet(request);

Expand Down
32 changes: 26 additions & 6 deletions src/rust/crates/ain-evm-ffi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ use std::error::Error;
#[cxx::bridge]
mod ffi {
extern "Rust" {
fn evm_add_balance(address: &str, amount: [u8; 32]) -> Result<()>;
fn evm_sub_balance(address: &str, amount: [u8; 32]) -> Result<()>;
fn evm_add_balance(context: u64, address: &str, amount: [u8; 32]) -> Result<()>;
fn evm_sub_balance(context: u64, address: &str, amount: [u8; 32]) -> Result<bool>;
fn evm_validate_raw_tx(tx: &str) -> Result<bool>;

fn evm_get_context() -> u64;
Expand All @@ -33,12 +33,32 @@ mod ffi {
}
}

pub fn evm_add_balance(address: &str, amount: [u8; 32]) -> Result<(), Box<dyn Error>> {
RUNTIME.handlers.evm.add_balance(address, amount.into())
pub fn evm_add_balance(
context: u64,
address: &str,
amount: [u8; 32],
) -> Result<(), Box<dyn Error>> {
let address = address.parse()?;
Ok(RUNTIME
.handlers
.evm
.add_balance(context, address, amount.into()))
}

pub fn evm_sub_balance(address: &str, amount: [u8; 32]) -> Result<(), Box<dyn Error>> {
RUNTIME.handlers.evm.sub_balance(address, amount.into())
pub fn evm_sub_balance(
context: u64,
address: &str,
amount: [u8; 32],
) -> Result<bool, Box<dyn Error>> {
let address = address.parse()?;
match RUNTIME
.handlers
.evm
.sub_balance(context, address, amount.into())
{
Ok(_) => Ok(true),
Err(_) => Ok(false),
}
}

pub fn evm_validate_raw_tx(tx: &str) -> Result<bool, Box<dyn Error>> {
Expand Down
Loading

0 comments on commit 326c823

Please sign in to comment.