Emissions: fund sysio.dclaim immediately on incoming OPP claim#354
Emissions: fund sysio.dclaim immediately on incoming OPP claim#354heifner wants to merge 5 commits into
Conversation
dclaim::onreward now inline-calls a new sysio.system::fundclaim action that drains the t5 pool to dclaim for the exact reward amount, so a staker can claim in the next block instead of waiting for the next pay-epoch. payepoch no longer transfers capital; the implicit capital reserve (period_emission minus compute / capex / governance) stays in sysio's balance until fundclaim pulls it. - Remove capital_bps from emission_config; setemitcfg validates compute + capex + governance <= 10000. The remainder is the implicit capital reserve. - Add t5_state.capital_shortfall_total; fundclaim accrues any unfunded delta here when the pool runs short, preserving the never-throw contract for opp inbound dispatch. - Remove epoch_log.capital_amount (always zero under this model).
…emissions-dclaim-instant-funding # Conflicts: # contracts/sysio.dclaim/sysio.dclaim.wasm
| auto state = t5s.get(); | ||
|
|
||
| const auto cfg = get_emit_cfg(get_self()); | ||
| const int64_t remaining = cfg.t5_distributable - cfg.t5_floor - state.total_distributed; |
There was a problem hiding this comment.
This caps fundclaim only by lifetime emission headroom, but ignores state.pending_emission_amount, which has already accrued for the current pay period at emissions.cpp (line 474). With pay_cadence_epochs > 1, a capital draw between accrue and payepoch can consume funds already scheduled for compute/capex/governance. The next payepoch then either blocks on insufficient balance or treasury exhaustion while pending_emission_amount remains unpaid. Cap the claim pool to the current period’s implicit capital reserve, or at least exclude pending payepoch obligations from the transferable amount.
There was a problem hiding this comment.
Addressed in 2b4e0d1. fundclaim now subtracts state.pending_emission_amount from the lifetime headroom cap, so a capital draw between accrueepoch and payepoch cannot consume the funds already scheduled for the next payepoch's compute/capex/governance distribution.
| const int64_t shortfall = amount - to_transfer; | ||
|
|
||
| if (to_transfer > 0) { | ||
| send_wire_transfer(get_self(), CAPITAL_ACCOUNT, to_transfer, memo::capital); |
There was a problem hiding this comment.
This still performs a real token transfer after only checking accounting headroom. If sysio’s actual WIRE balance is below to_transfer, sysio.token::transfer throws overdrawn balance at sysio.token.cpp (line 98). Since sysio.dclaim::onreward sends this inline at sysio.dclaim.cpp (line 252), the inbound OPP handler can still abort despite the “never throws” guarantee. Include actual sysio WIRE balance in the cap before sending the transfer.
There was a problem hiding this comment.
Addressed in 2b4e0d1. fundclaim now caps to sysio's actual WIRE balance (also less pending_emission_amount) before sending the transfer, so sysio.token::transfer cannot throw overdrawn balance from inside the inline STAKING_REWARD dispatch. The final transfer amount is std::min({amount, lifetime_headroom - pending, balance - pending}); any unfunded delta accrues to capital_shortfall_total.
…emissions-dclaim-instant-funding # Conflicts: # contracts/sysio.system/sysio.system.wasm
Addresses PR #354 review: - Subtract state.pending_emission_amount from the lifetime headroom cap so fundclaim cannot consume funds already accrued (via accrueepoch) for the next payepoch's compute/capital/capex/governance distribution. - Add an actual sysio WIRE balance cap (also less pending) so the inline sysio.token::transfer cannot throw "overdrawn balance". STAKING_REWARD dispatch from sysio.msgch is bound by the never-throw contract for OPP inbound handlers; an aborting transfer would propagate up and break envelope consensus. Transfer cap is now std::min({amount, accounting_available, balance_available}). Shortfall accrual to capital_shortfall_total is unchanged.
…claim-instant-funding # Conflicts: # contracts/sysio.system/sysio.system.wasm
jglanz
left a comment
There was a problem hiding this comment.
looks good; personally I'd like to chat about how the different basis points (bps) are applied/related, but generally the code seems fine
Summary
Replaces the curve-driven capital BPS share with immediate funding tied to actual OPP claim load.
sysio.dclaim::onrewardnow inline-calls a newsysio.system::fundclaimaction that transfers the exact credit amount fromsysio's pool tosysio.dclaim, so a staker can claim in the next block instead of waiting for the next pay-epoch.Model
payepochtransfers compute + capex + governance only. The "capital bucket" is gone -- the slot it used to occupy is now an implicit capital reserve (period_emission - compute - capex - governance) that stays insysio's balance.fundclaimdrains the pool against the implicit reserve in real time, one inline action per onreward. The reserve naturally absorbs the rounding dust from per-sharesplit_bpsfloors.fundclaimis asked for more than the pool has left, it transfers what's available and bumpst5_state.capital_shortfall_totalby the unfunded delta. It never throws (the OPP inbound dispatch chain must not be aborted by emissions-side conditions).ABI changes
emission_config.capital_bpsremoved.setemitcfgnow requirescompute_bps + capex_bps + governance_bps <= 10000.epoch_log.capital_amountremoved.t5_state.capital_shortfall_total(int64) added.sysio.system::fundclaim(int64_t amount)action, auth=sysio.dclaim.Pre-launch, so no migration shim.