Skip to content

Commit

Permalink
Merge pull request #305 from eosnetworkfoundation/native_deposit
Browse files Browse the repository at this point in the history
basic deposit & withdraw for native token
  • Loading branch information
spoonincode committed Feb 3, 2023
2 parents 2c635d1 + b9e7bbd commit 234654e
Show file tree
Hide file tree
Showing 6 changed files with 359 additions and 2 deletions.
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
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
3 changes: 1 addition & 2 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
${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 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 234654e

Please sign in to comment.