You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
README.md's feature table and API reference for stellar_send describe pause()/unpause(), transfer_admin()/accept_admin() two-step rotation, and ContractConfig.min_amount/max_amount bounds — but stellar_send/src/lib.rs's actual ContractConfig struct only has admin, fee_bps, fee_collector, active, and none of these functions exist in the #[contractimpl] block.
The same mismatch applies to fee_collector (README claims "Period limits" withdrawal feature, not implemented) and token_bridge (README claims "Supply cap" and pause/unpause, not implemented). This is misleading to integrators and should either be implemented or the README corrected to reflect current (v0.1.0) scope, distinguishing shipped vs. planned features — the stubs.rs files in each contract's src/ directory already contain an informal backlog that could seed a real roadmap section.
Additional Notes
Deeper technical detail
Beyond the README/implementation mismatch, there's a subtler bug hiding in the existing code that this issue should also cover: ContractConfig (stellar_send/src/lib.rs lines 62-73) already has an active: bool field, set to true unconditionally in initialize (line 135) — but grep across stellar_send/src/lib.rs, batch.rs, payment_request.rs, and subscription.rs shows no function ever reads config.active. The field is written once and never consulted, meaning even though the storage layout implies pause support exists, there is currently no way to actually pause the contract even at the raw storage level, and no pause()/unpause() mutator exists to flip it anyway. This is tracked as its own new issue in this batch ("ContractConfig.active field is fully dead code") since it's a distinct, more precisely scoped bug than the general README-drift described here.
Edge cases
If pause() is implemented, every fee-charging entry point (send_payment, send_batch_payment, send_path_payment, fulfill_payment_request, execute_subscription) needs the guard — it's easy to add it to send_payment and forget execute_subscription, especially since subscriptions are keeper-triggered and easy to overlook in manual QA.
Decide whether "paused" should still allow cancel_subscription / cancel_payment_request (probably yes — canceling should always be allowed) while blocking only value-moving calls.
Two-step admin rotation (transfer_admin/accept_admin) needs a pending-admin storage slot and must handle the case where accept_admin is never called (should cancel_admin_transfer, already listed in stubs.rs line 16, allow the current admin to abort a stuck transfer?).
Implementation sketch & tradeoffs
Add KEY_PAUSED: Symbol (or reuse config.active) plus pause()/unpause() gated on config.admin.require_auth(), and an assert_active(&config) helper called at the top of every value-moving entrypoint — this is a good candidate to share with the boilerplate-consolidation effort in issue Consolidate duplicated admin/init/error boilerplate shared across fee_collector, stellar_send, and token_bridge #9 since fee_collector and token_bridge would benefit from the identical pattern (their READMEs make similar unfulfilled claims per this issue's original body).
For admin rotation, the standard two-step pattern: transfer_admin(new_admin) stores KEY_PENDING_ADMIN (requiring current admin auth), accept_admin() requires new_admin.require_auth() and swaps KEY_ADMIN/clears KEY_PENDING_ADMIN.
Given the number of "planned but undocumented as such" features already itemized in stubs.rs for all three contracts, the pragmatic fix here is two-pronged: (a) correct the README immediately to describe v0.1.0 actual scope with a clearly labeled "Roadmap" section sourced from stubs.rs, and (b) implement pause/unpause and admin rotation as separate, reviewable PRs rather than one large change.
Testing strategy
Add a test asserting that once paused, send_payment returns a new StellarSendError::ContractPaused (or similar) variant rather than silently succeeding — note error.rs currently has no such variant, so this needs an addition to the error enum (bump from 22 variants).
Add round-trip tests for transfer_admin → accept_admin, and for cancel_admin_transfer clearing KEY_PENDING_ADMIN without swapping KEY_ADMIN.
Cross-check fee_collector and token_bridge READMEs/stubs for the same admin-rotation and pause claims so the fix is applied consistently, not just to stellar_send.
README.md's feature table and API reference forstellar_senddescribepause()/unpause(),transfer_admin()/accept_admin()two-step rotation, andContractConfig.min_amount/max_amountbounds — butstellar_send/src/lib.rs's actualContractConfigstruct only hasadmin,fee_bps,fee_collector,active, and none of these functions exist in the#[contractimpl]block.The same mismatch applies to
fee_collector(README claims "Period limits" withdrawal feature, not implemented) andtoken_bridge(README claims "Supply cap" and pause/unpause, not implemented). This is misleading to integrators and should either be implemented or the README corrected to reflect current (v0.1.0) scope, distinguishing shipped vs. planned features — thestubs.rsfiles in each contract'ssrc/directory already contain an informal backlog that could seed a real roadmap section.Additional Notes
Deeper technical detail
Beyond the README/implementation mismatch, there's a subtler bug hiding in the existing code that this issue should also cover:
ContractConfig(stellar_send/src/lib.rslines 62-73) already has anactive: boolfield, set totrueunconditionally ininitialize(line 135) — but grep acrossstellar_send/src/lib.rs,batch.rs,payment_request.rs, andsubscription.rsshows no function ever readsconfig.active. The field is written once and never consulted, meaning even though the storage layout implies pause support exists, there is currently no way to actually pause the contract even at the raw storage level, and nopause()/unpause()mutator exists to flip it anyway. This is tracked as its own new issue in this batch ("ContractConfig.active field is fully dead code") since it's a distinct, more precisely scoped bug than the general README-drift described here.Edge cases
pause()is implemented, every fee-charging entry point (send_payment,send_batch_payment,send_path_payment,fulfill_payment_request,execute_subscription) needs the guard — it's easy to add it tosend_paymentand forgetexecute_subscription, especially since subscriptions are keeper-triggered and easy to overlook in manual QA.cancel_subscription/cancel_payment_request(probably yes — canceling should always be allowed) while blocking only value-moving calls.transfer_admin/accept_admin) needs a pending-admin storage slot and must handle the case whereaccept_adminis never called (shouldcancel_admin_transfer, already listed instubs.rsline 16, allow the current admin to abort a stuck transfer?).Implementation sketch & tradeoffs
KEY_PAUSED: Symbol(or reuseconfig.active) pluspause()/unpause()gated onconfig.admin.require_auth(), and anassert_active(&config)helper called at the top of every value-moving entrypoint — this is a good candidate to share with the boilerplate-consolidation effort in issue Consolidate duplicated admin/init/error boilerplate shared across fee_collector, stellar_send, and token_bridge #9 sincefee_collectorandtoken_bridgewould benefit from the identical pattern (their READMEs make similar unfulfilled claims per this issue's original body).transfer_admin(new_admin)storesKEY_PENDING_ADMIN(requiring current admin auth),accept_admin()requiresnew_admin.require_auth()and swapsKEY_ADMIN/clearsKEY_PENDING_ADMIN.stubs.rsfor all three contracts, the pragmatic fix here is two-pronged: (a) correct the README immediately to describe v0.1.0 actual scope with a clearly labeled "Roadmap" section sourced fromstubs.rs, and (b) implementpause/unpauseand admin rotation as separate, reviewable PRs rather than one large change.Testing strategy
send_paymentreturns a newStellarSendError::ContractPaused(or similar) variant rather than silently succeeding — noteerror.rscurrently has no such variant, so this needs an addition to the error enum (bump from 22 variants).transfer_admin→accept_admin, and forcancel_admin_transferclearingKEY_PENDING_ADMINwithout swappingKEY_ADMIN.fee_collectorandtoken_bridgeREADMEs/stubs for the same admin-rotation and pause claims so the fix is applied consistently, not just tostellar_send.