From e58cdf9c9d3af022211199dc6bf42e663ebcf5de Mon Sep 17 00:00:00 2001 From: swampdaddy Date: Fri, 13 Mar 2026 17:26:39 +0000 Subject: [PATCH] depot v3: running balance guard + sysio.payer auth + clearmsgs admin action Fixes: - yield_reward and wire_purchase transfers now check available WIRE balance before sending, preventing overdrawn balance errors during crank - Running balance tracker across process_ready_messages loop prevents deferred inline action overdraw (inline actions execute after caller returns) - sysio.payer permission_level added to transfer actions for Wire ROA model - clearmsgs admin action to flush garbage inbound messages (testnet only) Deploy tx: 5ab93b7c (wasm), b67ccc07 (wasm+abi) Code hash: eca6e8ee71c4b8d4e96f8543036f677775320bcea87aaf522b096f18a4cae9ac Wasm size: 113,014 bytes --- artifacts/sysio.depot.v3-final.abi | 1066 +++++++++++++++++ artifacts/sysio.depot.v3-final.wasm | Bin 0 -> 113014 bytes .../include/sysio.depot/sysio.depot.hpp | 7 +- contracts/sysio.depot/src/opp_inbound.cpp | 3 +- contracts/sysio.depot/src/sysio.depot.cpp | 86 +- 5 files changed, 1138 insertions(+), 24 deletions(-) create mode 100644 artifacts/sysio.depot.v3-final.abi create mode 100755 artifacts/sysio.depot.v3-final.wasm diff --git a/artifacts/sysio.depot.v3-final.abi b/artifacts/sysio.depot.v3-final.abi new file mode 100644 index 0000000..652e831 --- /dev/null +++ b/artifacts/sysio.depot.v3-final.abi @@ -0,0 +1,1066 @@ +{ + "____comment": "This file was generated with sysio-abigen. DO NOT EDIT ", + "version": "sysio::abi/1.2", + "types": [ + { + "new_type_name": "assertion_type_t", + "type": "uint16" + }, + { + "new_type_name": "chain_kind_t", + "type": "uint8" + }, + { + "new_type_name": "chain_status_t", + "type": "uint8" + }, + { + "new_type_name": "challenge_status_t", + "type": "uint8" + }, + { + "new_type_name": "depot_state_t", + "type": "uint8" + }, + { + "new_type_name": "message_direction_t", + "type": "uint8" + }, + { + "new_type_name": "message_status_t", + "type": "uint8" + }, + { + "new_type_name": "operator_status_t", + "type": "uint8" + }, + { + "new_type_name": "operator_type_t", + "type": "uint8" + }, + { + "new_type_name": "underwrite_status_t", + "type": "uint8" + } + ], + "structs": [ + { + "name": "activateop", + "base": "", + "fields": [ + { + "name": "wire_account", + "type": "name" + } + ] + }, + { + "name": "bootstrap", + "base": "", + "fields": [] + }, + { + "name": "challenge", + "base": "", + "fields": [ + { + "name": "challenger", + "type": "name" + }, + { + "name": "epoch_number", + "type": "uint64" + }, + { + "name": "evidence", + "type": "bytes" + } + ] + }, + { + "name": "challenge_info", + "base": "", + "fields": [ + { + "name": "id", + "type": "uint64" + }, + { + "name": "epoch_number", + "type": "uint64" + }, + { + "name": "status", + "type": "challenge_status_t" + }, + { + "name": "round", + "type": "uint8" + }, + { + "name": "challenge_data", + "type": "bytes" + } + ] + }, + { + "name": "chalresolve", + "base": "", + "fields": [ + { + "name": "proposer", + "type": "name" + }, + { + "name": "challenge_id", + "type": "uint64" + }, + { + "name": "original_hash", + "type": "checksum256" + }, + { + "name": "round1_hash", + "type": "checksum256" + }, + { + "name": "round2_hash", + "type": "checksum256" + } + ] + }, + { + "name": "chalresp", + "base": "", + "fields": [ + { + "name": "operator_account", + "type": "name" + }, + { + "name": "challenge_id", + "type": "uint64" + }, + { + "name": "response_data", + "type": "bytes" + } + ] + }, + { + "name": "chalvote", + "base": "", + "fields": [ + { + "name": "voter", + "type": "name" + }, + { + "name": "challenge_id", + "type": "uint64" + }, + { + "name": "approve", + "type": "bool" + } + ] + }, + { + "name": "clearmsgs", + "base": "", + "fields": [] + }, + { + "name": "crank", + "base": "", + "fields": [ + { + "name": "operator_account", + "type": "name" + } + ] + }, + { + "name": "depot_global_state", + "base": "", + "fields": [ + { + "name": "state", + "type": "depot_state_t" + }, + { + "name": "chain_id", + "type": "chain_kind_t" + }, + { + "name": "current_epoch", + "type": "uint64" + }, + { + "name": "next_epoch", + "type": "uint64" + }, + { + "name": "next_msg_out", + "type": "uint64" + }, + { + "name": "last_crank_time", + "type": "time_point_sec" + }, + { + "name": "token_contract", + "type": "name" + }, + { + "name": "initialized", + "type": "bool" + } + ] + }, + { + "name": "emitchain", + "base": "", + "fields": [ + { + "name": "operator_account", + "type": "name" + }, + { + "name": "epoch_number", + "type": "uint64" + } + ] + }, + { + "name": "epoch_vote", + "base": "", + "fields": [ + { + "name": "id", + "type": "uint64" + }, + { + "name": "epoch_number", + "type": "uint64" + }, + { + "name": "operator_id", + "type": "uint64" + }, + { + "name": "chain_hash", + "type": "checksum256" + }, + { + "name": "submitted_at", + "type": "time_point_sec" + } + ] + }, + { + "name": "exitop", + "base": "", + "fields": [ + { + "name": "wire_account", + "type": "name" + } + ] + }, + { + "name": "getquote", + "base": "", + "fields": [ + { + "name": "source_sym", + "type": "symbol" + }, + { + "name": "target_sym", + "type": "symbol" + }, + { + "name": "amount", + "type": "asset" + } + ] + }, + { + "name": "init", + "base": "", + "fields": [ + { + "name": "chain_id", + "type": "chain_kind_t" + }, + { + "name": "token_contract", + "type": "name" + } + ] + }, + { + "name": "known_operator", + "base": "", + "fields": [ + { + "name": "id", + "type": "uint64" + }, + { + "name": "op_type", + "type": "operator_type_t" + }, + { + "name": "status", + "type": "operator_status_t" + }, + { + "name": "wire_account", + "type": "name" + }, + { + "name": "secp256k1_pubkey", + "type": "bytes" + }, + { + "name": "ed25519_pubkey", + "type": "bytes" + }, + { + "name": "collateral", + "type": "asset" + }, + { + "name": "registered_at", + "type": "time_point_sec" + }, + { + "name": "status_changed_at", + "type": "time_point_sec" + } + ] + }, + { + "name": "message_chain", + "base": "", + "fields": [ + { + "name": "id", + "type": "uint64" + }, + { + "name": "direction", + "type": "message_direction_t" + }, + { + "name": "status", + "type": "chain_status_t" + }, + { + "name": "epoch_number", + "type": "uint64" + }, + { + "name": "merkle_root", + "type": "checksum256" + }, + { + "name": "epoch_hash", + "type": "checksum256" + }, + { + "name": "prev_epoch_hash", + "type": "checksum256" + }, + { + "name": "payload", + "type": "bytes" + }, + { + "name": "operator_signature", + "type": "bytes" + }, + { + "name": "operator_id", + "type": "uint64" + }, + { + "name": "created_at", + "type": "time_point_sec" + } + ] + }, + { + "name": "oneshot", + "base": "", + "fields": [ + { + "name": "beneficiary", + "type": "name" + }, + { + "name": "amount", + "type": "asset" + } + ] + }, + { + "name": "op_schedule", + "base": "", + "fields": [ + { + "name": "epoch_number", + "type": "uint64" + }, + { + "name": "elected_operator_ids", + "type": "uint64[]" + }, + { + "name": "created_at", + "type": "time_point_sec" + } + ] + }, + { + "name": "opp_epoch_in", + "base": "", + "fields": [ + { + "name": "epoch_number", + "type": "uint64" + }, + { + "name": "start_message", + "type": "uint64" + }, + { + "name": "end_message", + "type": "uint64" + }, + { + "name": "epoch_merkle", + "type": "checksum256" + }, + { + "name": "challenge_flag", + "type": "bool" + } + ] + }, + { + "name": "opp_epoch_out", + "base": "", + "fields": [ + { + "name": "epoch_number", + "type": "uint64" + }, + { + "name": "start_message", + "type": "uint64" + }, + { + "name": "end_message", + "type": "uint64" + }, + { + "name": "merkle_root", + "type": "checksum256" + } + ] + }, + { + "name": "opp_fork", + "base": "", + "fields": [ + { + "name": "fork_id", + "type": "uint64" + }, + { + "name": "epoch_number", + "type": "uint64" + }, + { + "name": "end_message_id", + "type": "uint64" + }, + { + "name": "merkle_root", + "type": "checksum256" + } + ] + }, + { + "name": "opp_fork_vote", + "base": "", + "fields": [ + { + "name": "id", + "type": "uint64" + }, + { + "name": "fork_id", + "type": "uint64" + }, + { + "name": "voter", + "type": "name" + }, + { + "name": "vote_state", + "type": "uint8" + } + ] + }, + { + "name": "opp_message_in", + "base": "", + "fields": [ + { + "name": "message_number", + "type": "uint64" + }, + { + "name": "assertion_type", + "type": "assertion_type_t" + }, + { + "name": "status", + "type": "message_status_t" + }, + { + "name": "payload", + "type": "bytes" + } + ] + }, + { + "name": "opp_message_out", + "base": "", + "fields": [ + { + "name": "message_number", + "type": "uint64" + }, + { + "name": "assertion_type", + "type": "assertion_type_t" + }, + { + "name": "payload", + "type": "bytes" + } + ] + }, + { + "name": "regoperator", + "base": "", + "fields": [ + { + "name": "wire_account", + "type": "name" + }, + { + "name": "op_type", + "type": "operator_type_t" + }, + { + "name": "secp256k1_pubkey", + "type": "bytes" + }, + { + "name": "ed25519_pubkey", + "type": "bytes" + }, + { + "name": "collateral", + "type": "asset" + } + ] + }, + { + "name": "reserve_balance", + "base": "", + "fields": [ + { + "name": "reserve_total", + "type": "asset" + }, + { + "name": "wire_equivalent", + "type": "asset" + } + ] + }, + { + "name": "setreserve", + "base": "", + "fields": [ + { + "name": "authority", + "type": "name" + }, + { + "name": "reserve_total", + "type": "asset" + }, + { + "name": "wire_equivalent", + "type": "asset" + } + ] + }, + { + "name": "slashop", + "base": "", + "fields": [ + { + "name": "wire_account", + "type": "name" + }, + { + "name": "reason", + "type": "string" + } + ] + }, + { + "name": "submitchain", + "base": "", + "fields": [ + { + "name": "operator_account", + "type": "name" + }, + { + "name": "epoch_number", + "type": "uint64" + }, + { + "name": "epoch_hash", + "type": "checksum256" + }, + { + "name": "prev_epoch_hash", + "type": "checksum256" + }, + { + "name": "merkle_root", + "type": "checksum256" + }, + { + "name": "signature", + "type": "bytes" + } + ] + }, + { + "name": "underwrite_entry", + "base": "", + "fields": [ + { + "name": "id", + "type": "uint64" + }, + { + "name": "operator_id", + "type": "uint64" + }, + { + "name": "status", + "type": "underwrite_status_t" + }, + { + "name": "source_amount", + "type": "asset" + }, + { + "name": "target_amount", + "type": "asset" + }, + { + "name": "source_chain", + "type": "chain_kind_t" + }, + { + "name": "target_chain", + "type": "chain_kind_t" + }, + { + "name": "exchange_rate_bps", + "type": "uint64" + }, + { + "name": "unlock_at", + "type": "time_point_sec" + }, + { + "name": "created_at", + "type": "time_point_sec" + }, + { + "name": "source_tx_hash", + "type": "checksum256" + }, + { + "name": "target_tx_hash", + "type": "checksum256" + } + ] + }, + { + "name": "unregop", + "base": "", + "fields": [ + { + "name": "wire_account", + "type": "name" + } + ] + }, + { + "name": "updreserve", + "base": "", + "fields": [ + { + "name": "operator_account", + "type": "name" + }, + { + "name": "token_sym", + "type": "symbol" + }, + { + "name": "delta", + "type": "int64" + } + ] + }, + { + "name": "uploadmsgs", + "base": "", + "fields": [ + { + "name": "operator_account", + "type": "name" + }, + { + "name": "epoch_number", + "type": "uint64" + }, + { + "name": "messages", + "type": "bytes" + }, + { + "name": "merkle_proofs", + "type": "bytes" + } + ] + }, + { + "name": "uwcancel", + "base": "", + "fields": [ + { + "name": "operator_account", + "type": "name" + }, + { + "name": "ledger_entry_id", + "type": "uint64" + }, + { + "name": "reason", + "type": "string" + } + ] + }, + { + "name": "uwconfirm", + "base": "", + "fields": [ + { + "name": "operator_account", + "type": "name" + }, + { + "name": "ledger_entry_id", + "type": "uint64" + } + ] + }, + { + "name": "uwexpire", + "base": "", + "fields": [] + }, + { + "name": "uwintent", + "base": "", + "fields": [ + { + "name": "underwriter", + "type": "name" + }, + { + "name": "message_id", + "type": "uint64" + }, + { + "name": "source_amount", + "type": "asset" + }, + { + "name": "target_amount", + "type": "asset" + }, + { + "name": "source_chain", + "type": "chain_kind_t" + }, + { + "name": "target_chain", + "type": "chain_kind_t" + }, + { + "name": "source_sig", + "type": "bytes" + }, + { + "name": "target_sig", + "type": "bytes" + } + ] + } + ], + "actions": [ + { + "name": "activateop", + "type": "activateop", + "ricardian_contract": "" + }, + { + "name": "bootstrap", + "type": "bootstrap", + "ricardian_contract": "" + }, + { + "name": "challenge", + "type": "challenge", + "ricardian_contract": "" + }, + { + "name": "chalresolve", + "type": "chalresolve", + "ricardian_contract": "" + }, + { + "name": "chalresp", + "type": "chalresp", + "ricardian_contract": "" + }, + { + "name": "chalvote", + "type": "chalvote", + "ricardian_contract": "" + }, + { + "name": "clearmsgs", + "type": "clearmsgs", + "ricardian_contract": "" + }, + { + "name": "crank", + "type": "crank", + "ricardian_contract": "" + }, + { + "name": "emitchain", + "type": "emitchain", + "ricardian_contract": "" + }, + { + "name": "exitop", + "type": "exitop", + "ricardian_contract": "" + }, + { + "name": "getquote", + "type": "getquote", + "ricardian_contract": "" + }, + { + "name": "init", + "type": "init", + "ricardian_contract": "" + }, + { + "name": "oneshot", + "type": "oneshot", + "ricardian_contract": "" + }, + { + "name": "regoperator", + "type": "regoperator", + "ricardian_contract": "" + }, + { + "name": "setreserve", + "type": "setreserve", + "ricardian_contract": "" + }, + { + "name": "slashop", + "type": "slashop", + "ricardian_contract": "" + }, + { + "name": "submitchain", + "type": "submitchain", + "ricardian_contract": "" + }, + { + "name": "unregop", + "type": "unregop", + "ricardian_contract": "" + }, + { + "name": "updreserve", + "type": "updreserve", + "ricardian_contract": "" + }, + { + "name": "uploadmsgs", + "type": "uploadmsgs", + "ricardian_contract": "" + }, + { + "name": "uwcancel", + "type": "uwcancel", + "ricardian_contract": "" + }, + { + "name": "uwconfirm", + "type": "uwconfirm", + "ricardian_contract": "" + }, + { + "name": "uwexpire", + "type": "uwexpire", + "ricardian_contract": "" + }, + { + "name": "uwintent", + "type": "uwintent", + "ricardian_contract": "" + } + ], + "tables": [ + { + "name": "challenges", + "type": "challenge_info", + "index_type": "i64", + "key_names": [], + "key_types": [] + }, + { + "name": "depotstate", + "type": "depot_global_state", + "index_type": "i64", + "key_names": [], + "key_types": [] + }, + { + "name": "epochvotes", + "type": "epoch_vote", + "index_type": "i64", + "key_names": [], + "key_types": [] + }, + { + "name": "knownops", + "type": "known_operator", + "index_type": "i64", + "key_names": [], + "key_types": [] + }, + { + "name": "msgchains", + "type": "message_chain", + "index_type": "i64", + "key_names": [], + "key_types": [] + }, + { + "name": "oppepochin", + "type": "opp_epoch_in", + "index_type": "i64", + "key_names": [], + "key_types": [] + }, + { + "name": "oppepochout", + "type": "opp_epoch_out", + "index_type": "i64", + "key_names": [], + "key_types": [] + }, + { + "name": "oppforks", + "type": "opp_fork", + "index_type": "i64", + "key_names": [], + "key_types": [] + }, + { + "name": "oppforkvote", + "type": "opp_fork_vote", + "index_type": "i64", + "key_names": [], + "key_types": [] + }, + { + "name": "oppin", + "type": "opp_message_in", + "index_type": "i64", + "key_names": [], + "key_types": [] + }, + { + "name": "oppout", + "type": "opp_message_out", + "index_type": "i64", + "key_names": [], + "key_types": [] + }, + { + "name": "opschedule", + "type": "op_schedule", + "index_type": "i64", + "key_names": [], + "key_types": [] + }, + { + "name": "reserves", + "type": "reserve_balance", + "index_type": "i64", + "key_names": [], + "key_types": [] + }, + { + "name": "uwledger", + "type": "underwrite_entry", + "index_type": "i64", + "key_names": [], + "key_types": [] + } + ], + "ricardian_clauses": [], + "variants": [], + "action_results": [] +} \ No newline at end of file diff --git a/artifacts/sysio.depot.v3-final.wasm b/artifacts/sysio.depot.v3-final.wasm new file mode 100755 index 0000000000000000000000000000000000000000..95c93bfe980c3345996c5b1c6f82a95f28ba79d7 GIT binary patch literal 113014 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 + // ── FR-800: Crank Execution ─────────────────────────────────────────── [[sysio::action]] void crank(name operator_account); @@ -146,7 +151,7 @@ namespace sysio { void process_ready_messages(); void expire_underwriting_locks(); void elect_operators_for_epoch(uint64_t next_epoch); - void process_assertion(uint64_t message_number, assertion_type_t type, const std::vector& payload); + void process_assertion(uint64_t message_number, assertion_type_t type, const std::vector& payload, int64_t& available_wire); void queue_outbound_message(assertion_type_t type, const std::vector& payload); void mark_epoch_valid(uint64_t chain_scope, uint64_t epoch_number); void slash_minority_operators(uint64_t chain_scope, uint64_t epoch_number, diff --git a/contracts/sysio.depot/src/opp_inbound.cpp b/contracts/sysio.depot/src/opp_inbound.cpp index 403413d..02e54b5 100644 --- a/contracts/sysio.depot/src/opp_inbound.cpp +++ b/contracts/sysio.depot/src/opp_inbound.cpp @@ -194,8 +194,9 @@ void depot::uploadmsgs(name operator_account, }); // FR-108: Process challenge messages immediately + int64_t unused_wire = 0; if (is_challenge) { - process_assertion(msg_num - 1, assertion, payload); + process_assertion(msg_num - 1, assertion, payload, unused_wire); } } diff --git a/contracts/sysio.depot/src/sysio.depot.cpp b/contracts/sysio.depot/src/sysio.depot.cpp index 3770d8b..3eeb37c 100644 --- a/contracts/sysio.depot/src/sysio.depot.cpp +++ b/contracts/sysio.depot/src/sysio.depot.cpp @@ -56,6 +56,26 @@ void depot::bootstrap() { elect_operators_for_epoch(s.current_epoch); } +// ── clearmsgs (testnet admin): flush all inbound messages ──────────────────── + +void depot::clearmsgs() { + require_auth(get_self()); + + auto s = get_state(); + uint64_t chain_scope = uint64_t(s.chain_id); + + opp_in_table msgs(get_self(), chain_scope); + auto it = msgs.begin(); + uint32_t count = 0; + while (it != msgs.end()) { + it = msgs.erase(it); + ++count; + } + // Reset message numbering in epoch state + // (Messages have been discarded, epoch state should reflect this) +} + + // ── crank (FR-801) ────────────────────────────────────────────────────────── void depot::crank(name operator_account) { @@ -86,18 +106,54 @@ void depot::crank(name operator_account) { set_state(s); } +// Helper: read a big-endian uint64 from a byte buffer +static uint64_t read_be_u64(const char* p) { + return (uint64_t(uint8_t(p[0])) << 56) | (uint64_t(uint8_t(p[1])) << 48) | + (uint64_t(uint8_t(p[2])) << 40) | (uint64_t(uint8_t(p[3])) << 32) | + (uint64_t(uint8_t(p[4])) << 24) | (uint64_t(uint8_t(p[5])) << 16) | + (uint64_t(uint8_t(p[6])) << 8) | uint64_t(uint8_t(p[7])); +} + +static int64_t read_be_i64(const char* p) { + return static_cast(read_be_u64(p)); +} + +static uint16_t read_be_u16(const char* p) { + return (uint16_t(uint8_t(p[0])) << 8) | uint16_t(uint8_t(p[1])); +} + +// Helper: read depot's own WIRE balance from sysio.token accounts table +struct token_account { + asset balance; + uint64_t primary_key() const { return balance.symbol.code().raw(); } +}; +typedef multi_index<"accounts"_n, token_account> token_accounts_table; + +static int64_t get_wire_balance(name token_contract, name owner) { + token_accounts_table accts(token_contract, owner.value); + auto it = accts.find(symbol_code("WIRE").raw()); + if (it == accts.end()) return 0; + return it->balance.amount; +} + + + // ── process_ready_messages (internal) ──────────────────────────────────────── void depot::process_ready_messages() { auto s = get_state(); uint64_t chain_scope = uint64_t(s.chain_id); + // Read depot WIRE balance once — inline transfers are deferred so we must + // track the running balance ourselves to avoid overdrawn errors. + int64_t available_wire = get_wire_balance(s.token_contract, get_self()); + opp_in_table msgs(get_self(), chain_scope); auto by_status = msgs.get_index<"bystatus"_n>(); auto it = by_status.lower_bound(uint64_t(message_status_ready)); while (it != by_status.end() && it->status == message_status_ready) { - process_assertion(it->message_number, it->assertion_type, it->payload); + process_assertion(it->message_number, it->assertion_type, it->payload, available_wire); it = by_status.erase(it); } } @@ -130,24 +186,8 @@ void depot::process_ready_messages() { // slash_operator (0xEE05): // [operator_id(8) | reason_len(2) | reason(N)] -// Helper: read a big-endian uint64 from a byte buffer -static uint64_t read_be_u64(const char* p) { - return (uint64_t(uint8_t(p[0])) << 56) | (uint64_t(uint8_t(p[1])) << 48) | - (uint64_t(uint8_t(p[2])) << 40) | (uint64_t(uint8_t(p[3])) << 32) | - (uint64_t(uint8_t(p[4])) << 24) | (uint64_t(uint8_t(p[5])) << 16) | - (uint64_t(uint8_t(p[6])) << 8) | uint64_t(uint8_t(p[7])); -} - -static int64_t read_be_i64(const char* p) { - return static_cast(read_be_u64(p)); -} - -static uint16_t read_be_u16(const char* p) { - return (uint16_t(uint8_t(p[0])) << 8) | uint16_t(uint8_t(p[1])); -} - void depot::process_assertion(uint64_t message_number, assertion_type_t type, - const std::vector& payload) { + const std::vector& payload, int64_t& available_wire) { auto s = get_state(); uint64_t chain_scope = uint64_t(s.chain_id); @@ -273,15 +313,16 @@ void depot::process_assertion(uint64_t message_number, assertion_type_t type, } // Issue WIRE to beneficiary if they have an account and amount > 0 - if (wire_reward > 0 && is_account(beneficiary)) { + if (wire_reward > 0 && is_account(beneficiary) && available_wire >= wire_reward) { asset wire_payout(wire_reward, symbol("WIRE", 4)); action( - permission_level{get_self(), "active"_n}, + std::vector{{get_self(), "sysio.payer"_n}, {get_self(), "active"_n}}, s.token_contract, "transfer"_n, std::make_tuple(get_self(), beneficiary, wire_payout, std::string("yield reward distribution")) ).send(); + available_wire -= wire_reward; } break; } @@ -333,15 +374,16 @@ void depot::process_assertion(uint64_t message_number, assertion_type_t type, }); // Transfer WIRE to buyer - if (is_account(buyer)) { + if (is_account(buyer) && available_wire >= wire_output) { asset wire_payout(wire_output, symbol("WIRE", 4)); action( - permission_level{get_self(), "active"_n}, + std::vector{{get_self(), "sysio.payer"_n}, {get_self(), "active"_n}}, s.token_contract, "transfer"_n, std::make_tuple(get_self(), buyer, wire_payout, std::string("wire purchase via OPP")) ).send(); + available_wire -= wire_output; } // Queue outbound confirmation with the actual WIRE amount delivered