提交 b743a1a8 编写于 作者: N Nathan Hourt

Ref #15: Further integrate native contracts

Define notify handlers and require notifications be set correctly for
messages moving funds from liquid to staked and back, so balances are
tracked as they move between contracts
上级 f89c3ab7
......@@ -66,7 +66,7 @@
#define OBJECT_CTOR(...) BOOST_PP_OVERLOAD(OBJECT_CTOR, __VA_ARGS__)(__VA_ARGS__)
#define EOS_SYSTEM_CONTRACT_FUNCTIONS (CreateAccount)(DefineStruct)(SetMessageHandler)
#define EOS_CONTRACT_FUNCTIONS (Transfer)
#define EOS_CONTRACT_FUNCTIONS (Transfer)(TransferToLocked)
#define EOS_STAKED_BALANCE_CONTRACT_FUNCTIONS (CreateProducer)(UpdateProducer)
namespace eos { namespace chain {
......
......@@ -30,6 +30,7 @@ void Transfer::apply(apply_context& context) {
auto transfer = context.msg.as<types::Transfer>();
const auto& from = db.get<account_object,by_name>(transfer.from);
const auto& to = db.get<account_object,by_name>(transfer.to);
#warning TODO: move balance from account_object to an EOS-constract-specific object
db.modify(from, [&](account_object& a) {
a.balance -= transfer.amount;
});
......@@ -38,4 +39,41 @@ void Transfer::apply(apply_context& context) {
});
}
void TransferToLocked::validate(message_validate_context& context) {
auto lock = context.msg.as<types::TransferToLocked>();
EOS_ASSERT(lock.amount > 0, message_validate_exception, "Locked amount must be positive");
EOS_ASSERT(lock.to == lock.from || context.msg.has_notify(lock.to),
message_validate_exception, "Recipient account must be notified");
EOS_ASSERT(context.msg.has_notify(config::StakedBalanceContractName), message_validate_exception,
"Staked Balance Contract (${name}) must be notified", ("name", config::StakedBalanceContractName));
}
void TransferToLocked::validate_preconditions(precondition_validate_context& context) {
auto lock = context.msg.as<types::TransferToLocked>();
ShareType balance;
try {
const auto& sender = context.db.get<account_object, by_name>(lock.from);
context.db.get<account_object, by_name>(lock.to);
balance = sender.balance.amount;
} EOS_RECODE_EXC(fc::exception, message_precondition_exception)
EOS_ASSERT(balance >= lock.amount, message_precondition_exception,
"Account ${a} lacks sufficient funds to lock ${amt} EOS", ("a", lock.from)("amt", lock.amount));
}
void TransferToLocked::apply(apply_context& context) {
auto lock = context.msg.as<types::TransferToLocked>();
const auto& locker = context.db.get<account_object, by_name>(lock.from);
context.mutable_db.modify(locker, [&lock](account_object& a) {
a.balance.amount -= lock.amount;
});
}
void ClaimUnlockedEos_Notify_Eos(apply_context& context) {
auto claim = context.msg.as<types::ClaimUnlockedEos>();
const auto& claimant = context.db.get<account_object, by_name>(claim.account);
context.mutable_db.modify(claimant, [&claim](account_object& a) {
a.balance.amount += claim.amount;
});
}
} // namespace eos
......@@ -12,4 +12,12 @@ struct Transfer {
static void apply(chain::apply_context& context);
};
struct TransferToLocked {
static void validate(chain::message_validate_context& context);
static void validate_preconditions(chain::precondition_validate_context& context);
static void apply(chain::apply_context& context);
};
void ClaimUnlockedEos_Notify_Eos(chain::apply_context& context);
} // namespace eos
......@@ -6,11 +6,7 @@
namespace eos {
struct TransferToLocked {
static void validate(chain::message_validate_context& context);
static void validate_preconditions(chain::precondition_validate_context& context);
static void apply(chain::apply_context& context);
};
void TransferToLocked_Notify_Staked(chain::apply_context& context);
struct StartUnlockEos {
static void validate(chain::message_validate_context& context);
......
......@@ -43,9 +43,17 @@ void native_system_contract_plugin::install(chain_controller& db) {
db.set_apply_handler(contractname, contractname, #handlername, &handlername::apply);
#define FWD_SET_HANDLERS(r, data, elem) SET_HANDLERS(data, elem)
// Set message handlers
BOOST_PP_SEQ_FOR_EACH(FWD_SET_HANDLERS, config::SystemContractName, EOS_SYSTEM_CONTRACT_FUNCTIONS)
BOOST_PP_SEQ_FOR_EACH(FWD_SET_HANDLERS, config::EosContractName, EOS_CONTRACT_FUNCTIONS)
BOOST_PP_SEQ_FOR_EACH(FWD_SET_HANDLERS, config::StakedBalanceContractName, EOS_STAKED_BALANCE_CONTRACT_FUNCTIONS)
// Set notify handlers
db.set_apply_handler(config::EosContractName, config::StakedBalanceContractName,
"TransferToLocked", &TransferToLocked_Notify_Staked);
db.set_apply_handler(config::StakedBalanceContractName, config::EosContractName,
"ClaimUnlockedEos", &ClaimUnlockedEos_Notify_Eos);
#warning TODO: Notify eos and sbc when an account is created
}
}
......@@ -10,34 +10,12 @@
namespace eos {
using namespace chain;
void TransferToLocked::validate(message_validate_context& context) {
void TransferToLocked_Notify_Staked(apply_context& context) {
auto lock = context.msg.as<types::TransferToLocked>();
EOS_ASSERT(lock.amount > 0, message_validate_exception, "Locked amount must be positive");
EOS_ASSERT(lock.to == lock.from || context.msg.has_notify(lock.to),
message_validate_exception, "Recipient account must be notified");
#warning TODO: check that staked balance contract is notified (what's that contract's name?...)
}
void TransferToLocked::validate_preconditions(precondition_validate_context& context) {
auto lock = context.msg.as<types::TransferToLocked>();
ShareType balance;
try {
const auto& sender = context.db.get<account_object, by_name>(lock.from);
context.db.get<account_object, by_name>(lock.to);
balance = sender.balance.amount;
} EOS_RECODE_EXC(fc::exception, message_precondition_exception)
EOS_ASSERT(balance >= lock.amount, message_precondition_exception,
"Account ${a} lacks sufficient funds to lock ${amt} EOS", ("a", lock.from)("amt", lock.amount));
#warning TODO: check that account still has minimum balance?... Eww, that's gonna get complicated
}
void TransferToLocked::apply(apply_context& context) {
auto lock = context.msg.as<types::TransferToLocked>();
const auto& locker = context.db.get<account_object, by_name>(lock.from);
context.mutable_db.modify(locker, [&lock](account_object& a) {
a.balance.amount -= lock.amount;
const auto& balance = context.db.get<StakedBalanceObject, byOwnerName>(lock.to);
context.mutable_db.modify(balance, [&lock](StakedBalanceObject& sbo) {
sbo.stakedBalance += lock.amount;
});
#warning TODO: Credit amount to staked balance (but this contract doesn't do that...)
}
void StartUnlockEos::validate(message_validate_context& context) {
......@@ -72,6 +50,8 @@ void StartUnlockEos::apply(apply_context& context) {
void ClaimUnlockedEos::validate(message_validate_context& context) {
auto claim = context.msg.as<types::ClaimUnlockedEos>();
EOS_ASSERT(claim.amount > 0, message_validate_exception, "Claim amount must be positive");
EOS_ASSERT(context.msg.has_notify(config::EosContractName), message_validate_exception,
"EOS Contract (${name}) must be notified", ("name", config::EosContractName));
}
void ClaimUnlockedEos::validate_preconditions(precondition_validate_context& context) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册