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

Dev Feature 300 - Renting Assets Version B #10

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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
22 changes: 21 additions & 1 deletion include/atomicassets.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,13 @@ CONTRACT atomicassets : public contract {
string memo
);

ACTION move(
name owner,
name from,
name to,
vector <uint64_t> asset_ids,
string memo
);

ACTION createcol(
name author,
Expand Down Expand Up @@ -269,6 +276,19 @@ CONTRACT atomicassets : public contract {
typedef multi_index <name("collections"), collections_s> collections_t;


TABLE holders_s {
uint64_t asset_id;
name holder;
name owner;

uint64_t primary_key() const { return asset_id; };
uint64_t by_holder() const { return holder.value; };
};

typedef multi_index <name("holders"), holders_s,
indexed_by<name("holder"), const_mem_fun <holders_s, uint64_t, &holders_s::by_holder>>>
holders_t;

//Scope: collection_name
TABLE schemas_s {
name schema_name;
Expand Down Expand Up @@ -312,7 +332,6 @@ CONTRACT atomicassets : public contract {

typedef multi_index <name("assets"), assets_s> assets_t;


TABLE offers_s {
uint64_t offer_id;
name sender;
Expand Down Expand Up @@ -365,6 +384,7 @@ CONTRACT atomicassets : public contract {


collections_t collections = collections_t(get_self(), get_self().value);
holders_t holders = holders_t(get_self(), get_self().value);
offers_t offers = offers_t(get_self(), get_self().value);
balances_t balances = balances_t(get_self(), get_self().value);
config_t config = config_t(get_self(), get_self().value);
Expand Down
85 changes: 84 additions & 1 deletion src/atomicassets.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#include <atomicassets.hpp>


/**
* Initializes the config table. Only needs to be called once when first deploying the contract
* @required_auth The contract itself
Expand Down Expand Up @@ -81,6 +80,77 @@ ACTION atomicassets::transfer(
internal_transfer(from, to, asset_ids, memo, from);
}

/**
* Moves one or more assets to another account
* @required_auth of the true owner of the asset
* Cannot have notifications for the from & to, exploitable
*/
ACTION atomicassets::move(
name owner,
name from,
name to,
vector <uint64_t> asset_ids,
string memo
) {
require_auth(owner);
require_recipient(owner);

check(is_account(from), "from account does not exist");
check(is_account(to), "to account does not exist");

check(from != to, "from & to fields cannot be the same");

check(asset_ids.size() != 0, "asset_ids needs to contain at least one id");
check(memo.length() <= 256, "A move memo can only be 256 characters max");

vector <uint64_t> asset_ids_copy = asset_ids;
std::sort(asset_ids_copy.begin(), asset_ids_copy.end());
check(std::adjacent_find(asset_ids_copy.begin(), asset_ids_copy.end()) == asset_ids_copy.end(),
"Can't move the same asset multiple times");

assets_t owner_assets = get_assets(owner);

for (uint64_t & asset_id : asset_ids) {
auto asset_itr = owner_assets.require_find(asset_id,
("Owner doesn't own at least one of the provided assets (ID: " +
to_string(asset_id) + ")").c_str());

//Existence doesn't have to be checked because this always has to exist
if (asset_itr->template_id >= 0) {
templates_t collection_templates = get_templates(asset_itr->collection_name);

auto template_itr = collection_templates.find(asset_itr->template_id);
check(template_itr->transferable,
("At least one asset isn't transferable (ID: " + to_string(asset_id) + ")").c_str());
}

auto holders_itr = holders.find(asset_id);
if (holders_itr == holders.end()){
check(from == owner,
("Only the owner can move this asset (ID: " + to_string(asset_id) + ")").c_str());
// Emplaces new holder
holders.emplace(owner, [&](auto &_holders_row){
_holders_row.asset_id = asset_id;
_holders_row.holder = to;
_holders_row.owner = owner;
});
}

if (holders_itr != holders.end()){
check(holders_itr->holder == from,
("At least one asset invalidates the 'from:holder' constraint (ID: " + to_string(asset_id) + ")").c_str());

// Deletes row if returning to owner
if (to == owner){
holders.erase(holders_itr);
} else { // Modifies row to move holdership to the new "to" wallet
holders.modify(holders_itr, owner, [&](auto &_holders_row){
_holders_row.holder = to;
});
}
}
}
}

/**
* Creates a new collection
Expand Down Expand Up @@ -1268,6 +1338,19 @@ void atomicassets::internal_transfer(
("At least one asset isn't transferable (ID: " + to_string(asset_id) + ")").c_str());
}

auto holders_itr = holders.find(asset_id);
if (holders_itr != holders.end()){

// Deletes row if transfering to holder
if (to == holders_itr->holder){
holders.erase(holders_itr);
} else { // Modifies row to move ownership to the new "to" wallet
holders.modify(holders_itr, from, [&](auto &_holders_row){
_holders_row.owner = to;
});
}
}

//This is needed for sending notifications later
if (collection_to_assets_transferred.find(asset_itr->collection_name) !=
collection_to_assets_transferred.end()) {
Expand Down