Skip to content

Commit

Permalink
Merge branch 'main' into zach-contract-ci
Browse files Browse the repository at this point in the history
  • Loading branch information
kj4ezj committed Feb 8, 2023
2 parents 51590e9 + 5d9a9cf commit 1b7ff4e
Show file tree
Hide file tree
Showing 9 changed files with 386 additions and 23 deletions.
20 changes: 20 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# archives
*.7z
*.iso
*.rar
*.tar
*.tar.gz
*.tgz
Expand Down Expand Up @@ -28,12 +30,21 @@ cmake-build-debug

# data
*.csv
*.db
*.dbf
*.fods
*.html
*.json
*.ods
*.ots
*.tsv
*.uos
*.xhtml
*.xls
*.xlsm
*.xlsx
*.xlt
*.xltx
*.xml

# editor files
Expand All @@ -43,9 +54,18 @@ cmake-build-debug
.vscode

# executables
*.apk
*.app
*.AppImage
*.com
*.deb
*.dll
*.dmg
*.exe
*.jar
*.msi
*.out
*.rpm

# logs
*.log
Expand Down
45 changes: 45 additions & 0 deletions contract/include/evm_runtime/eosio.token.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#pragma once

#include <eosio/asset.hpp>
#include <eosio/eosio.hpp>

#include <string>

namespace eosio {

using std::string;

class [[eosio::contract("eosio.token")]] token : public contract {
public:
using contract::contract;

[[eosio::action]]
void create( const name& issuer,
const asset& maximum_supply);

[[eosio::action]]
void issue( const name& to, const asset& quantity, const string& memo );

[[eosio::action]]
void retire( const asset& quantity, const string& memo );

[[eosio::action]]
void transfer( const name& from,
const name& to,
const asset& quantity,
const string& memo );

[[eosio::action]]
void open( const name& owner, const symbol& symbol, const name& ram_payer );

[[eosio::action]]
void close( const name& owner, const symbol& symbol );

using create_action = eosio::action_wrapper<"create"_n, &token::create>;
using issue_action = eosio::action_wrapper<"issue"_n, &token::issue>;
using retire_action = eosio::action_wrapper<"retire"_n, &token::retire>;
using transfer_action = eosio::action_wrapper<"transfer"_n, &token::transfer>;
using open_action = eosio::action_wrapper<"open"_n, &token::open>;
using close_action = eosio::action_wrapper<"close"_n, &token::close>;
};
}
22 changes: 22 additions & 0 deletions contract/include/evm_runtime/evm_contract.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,18 @@ CONTRACT evm_contract : public contract {
[[eosio::action]]
void pushtx(eosio::name ram_payer, const bytes& rlptx);

[[eosio::action]]
void open(eosio::name owner, eosio::name ram_payer);

[[eosio::action]]
void close(eosio::name owner);

[[eosio::on_notify("eosio.token::transfer")]]
void transfer(eosio::name from, eosio::name to, eosio::asset quantity, std::string memo);

[[eosio::action]]
void withdraw(eosio::name owner, eosio::asset quantity);

/// @return true if all garbage has been collected
[[eosio::action]]
bool gc(uint32_t max);
Expand All @@ -37,6 +49,16 @@ CONTRACT evm_contract : public contract {
ACTION setbal(const bytes& addy, const bytes& bal);
#endif
private:
struct [[eosio::table]] [[eosio::contract("evm_contract")]] account {
name owner;
asset balance;
uint64_t dust = 0;

uint64_t primary_key() const { return owner.value; }
};

typedef eosio::multi_index<"accounts"_n, account> accounts;

struct [[eosio::table]] [[eosio::contract("evm_contract")]] config {
eosio::unsigned_int version; //placeholder for future variant index
uint64_t chainid = 0;
Expand Down
8 changes: 1 addition & 7 deletions contract/include/evm_runtime/tables.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,11 @@ struct [[eosio::table]] [[eosio::contract("evm_contract")]] account {
bytes eth_address;
uint64_t nonce;
bytes balance;
name eos_account;
bytes code;
bytes code_hash;

uint64_t primary_key()const { return id; }

uint64_t by_eos_account()const {
return eos_account.value;
}

checksum256 by_eth_address()const {
return make_key(eth_address);
}
Expand All @@ -43,12 +38,11 @@ struct [[eosio::table]] [[eosio::contract("evm_contract")]] account {
return res;
}

EOSLIB_SERIALIZE(account, (id)(eth_address)(nonce)(balance)(eos_account)(code)(code_hash));
EOSLIB_SERIALIZE(account, (id)(eth_address)(nonce)(balance)(code)(code_hash));
};

typedef multi_index< "account"_n, account,
indexed_by<"by.address"_n, const_mem_fun<account, checksum256, &account::by_eth_address>>,
indexed_by<"by.account"_n, const_mem_fun<account, uint64_t, &account::by_eos_account>>,
indexed_by<"by.codehash"_n, const_mem_fun<account, checksum256, &account::by_code_hash>>
> account_table;

Expand Down
62 changes: 62 additions & 0 deletions contract/src/actions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <evm_runtime/state.hpp>
#include <evm_runtime/engine.hpp>
#include <evm_runtime/intrinsics.hpp>
#include <evm_runtime/eosio.token.hpp>

#ifdef WITH_TEST_ACTIONS
#include <evm_runtime/test/engine.hpp>
Expand All @@ -17,6 +18,9 @@
#define LOGTIME(MSG)
#endif

static constexpr eosio::name token_account("eosio.token"_n);
static constexpr eosio::symbol token_symbol("EOS", 4u);

namespace evm_runtime {

using namespace silkworm;
Expand Down Expand Up @@ -69,6 +73,64 @@ void evm_contract::pushtx( eosio::name ram_payer, const bytes& rlptx ) {
LOGTIME("EVM EXECUTE");
}

void evm_contract::open(eosio::name owner, eosio::name ram_payer) {
assert_inited();
require_auth(ram_payer);
check(is_account(owner), "owner account does not exist");

accounts account_table(get_self(), get_self().value);
if(account_table.find(owner.value) == account_table.end())
account_table.emplace(ram_payer, [&](account& a) {
a.owner = owner;
a.balance = asset(0, token_symbol);
});
}

void evm_contract::close(eosio::name owner) {
assert_inited();
require_auth(owner);

accounts account_table(get_self(), get_self().value);
const account& owner_account = account_table.get(owner.value, "account is not open");

eosio::check(owner_account.balance.amount == 0 && owner_account.dust == 0, "cannot close because balance is not zero");
account_table.erase(owner_account);
}

void evm_contract::transfer(eosio::name from, eosio::name to, eosio::asset quantity, std::string memo) {
assert_inited();

if(to != get_self() || from == get_self())
return;

eosio::check(!memo.empty(), "memo must be already opened account name to credit deposit to");

eosio::name receiver(memo);

accounts account_table(get_self(), get_self().value);
const account& receiver_account = account_table.get(receiver.value, "receiving account has not been opened");

account_table.modify(receiver_account, eosio::same_payer, [&](account& a) {
a.balance += quantity;
});
}

void evm_contract::withdraw(eosio::name owner, eosio::asset quantity) {
assert_inited();
require_auth(owner);

accounts account_table(get_self(), get_self().value);
const account& owner_account = account_table.get(owner.value, "account is not open");

check(owner_account.balance.amount >= quantity.amount, "overdrawn balance");
account_table.modify(owner_account, eosio::same_payer, [&](account& a) {
a.balance -= quantity;
});

token::transfer_action transfer_act(token_account, {{get_self(), "active"_n}});
transfer_act.send(get_self(), owner, quantity, std::string("Withdraw from EVM balance"));
}

bool evm_contract::gc(uint32_t max) {
assert_inited();

Expand Down
7 changes: 4 additions & 3 deletions contract/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,12 @@ include_directories(
${CMAKE_SOURCE_DIR}/../../silkworm/third_party/silkpre/third_party/secp256k1/include
)

#file(GLOB UNIT_TESTS "*.cpp" "*.hpp")

set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -Wno-deprecated-declarations")

add_eosio_test( unit_test
add_eosio_test_executable( unit_test
${CMAKE_SOURCE_DIR}/evm_runtime_tests.cpp
${CMAKE_SOURCE_DIR}/init_tests.cpp
${CMAKE_SOURCE_DIR}/native_token_tests.cpp
${CMAKE_SOURCE_DIR}/main.cpp
${CMAKE_SOURCE_DIR}/silkworm/core/silkworm/rlp/encode.cpp
${CMAKE_SOURCE_DIR}/silkworm/core/silkworm/rlp/decode.cpp
Expand All @@ -42,3 +41,5 @@ add_eosio_test( unit_test
${CMAKE_SOURCE_DIR}/../external/ethash/lib/ethash/ethash.cpp
${CMAKE_SOURCE_DIR}/../external/ethash/lib/ethash/primes.c
)

add_test(NAME unit_test COMMAND unit_test --report_level=detailed --color_output -- --eos-vm-oc)
16 changes: 3 additions & 13 deletions contract/tests/evm_runtime_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,6 @@ struct account {
bytes eth_address;
uint64_t nonce;
bytes balance;
name eos_account;
bytes code;
bytes code_hash;

Expand All @@ -250,13 +249,6 @@ struct account {
}
};

struct by_account {
typedef index64_object index_object;
static name index_name() {
return account::index_name("by.account"_n);
}
};

struct by_codehash {
typedef index256_object index_object;
static name index_name() {
Expand All @@ -280,13 +272,11 @@ struct account {
static name index_name(const name& n) {
uint64_t index_table_name = table_name().to_uint64_t() & 0xFFFFFFFFFFFFFFF0ULL;

//0=>by.address, 1=>by.account, 2=>by.codehash
//0=>by.address, 1=>by.codehash
if( n == "by.address"_n ) {
return name{index_table_name | 0};
} else if( n == "by.account"_n ) {
return name{index_table_name | 1};
} else if( n == "by.codehash"_n ) {
return name{index_table_name | 2};
return name{index_table_name | 1};
}

dlog("index name not found: ${a}", ("a",n.to_string()));
Expand Down Expand Up @@ -320,7 +310,7 @@ struct account {
}

};
FC_REFLECT(account, (id)(eth_address)(nonce)(balance)(eos_account)(code)(code_hash));
FC_REFLECT(account, (id)(eth_address)(nonce)(balance)(code)(code_hash));

struct storage {
uint64_t id;
Expand Down
11 changes: 11 additions & 0 deletions contract/tests/init_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,17 @@ BOOST_FIXTURE_TEST_CASE(check_init, basic_evm_tester) try {
eosio_assert_message_exception,
[](const eosio_assert_message_exception& e) {return testing::expect_assert_message(e, "assertion failure with message: contract not initialized");});

BOOST_REQUIRE_EXCEPTION(push_action("evm"_n, "open"_n, "evm"_n, mvo()("owner", "evm"_n)("ram_payer", "evm"_n)),
eosio_assert_message_exception,
[](const eosio_assert_message_exception& e) {return testing::expect_assert_message(e, "assertion failure with message: contract not initialized");});
BOOST_REQUIRE_EXCEPTION(push_action("evm"_n, "close"_n, "evm"_n, mvo()("owner", "evm"_n)),
eosio_assert_message_exception,
[](const eosio_assert_message_exception& e) {return testing::expect_assert_message(e, "assertion failure with message: contract not initialized");});
BOOST_REQUIRE_EXCEPTION(push_action("evm"_n, "withdraw"_n, "evm"_n, mvo()("owner", "evm"_n)("quantity", asset())),
eosio_assert_message_exception,
[](const eosio_assert_message_exception& e) {return testing::expect_assert_message(e, "assertion failure with message: contract not initialized");});
// Test of transfer notification w/o init is handled in native_token_evm_tests/transfer_notifier_without_init test as it requires additional setup

BOOST_REQUIRE_EXCEPTION(push_action("evm"_n, "testtx"_n, "evm"_n, mvo()("rlptx", bytes())("bi", mvo()("coinbase", bytes())("difficulty", 0)("gasLimit", 0)("number", 0)("timestamp", 0))),
eosio_assert_message_exception,
[](const eosio_assert_message_exception& e) {return testing::expect_assert_message(e, "assertion failure with message: contract not initialized");});
Expand Down
Loading

0 comments on commit 1b7ff4e

Please sign in to comment.