Skip to content

Failed post-delegation actions leave the account stuck under dlp on base #95

Description

@bzawisto

Summary

When a delegated account's post-delegation actions fail, the validator schedules the automatic undelegation, but dlp rejects the base transaction with InstructionError(2, Custom(0)) (DlpError::InvalidAuthority). The account stays owned by dlp on base. The intent is stored as failed and is never retried.

Environment

  • magicblock-validator dev @ 9cc3fd1a, dlp pin dcd46dc
  • base: local test validator, dlp cloned from mainnet (2026-04-29 build)
  • reproduced twice with redsuite redshift/post_delegation_token_transfer

Steps to reproduce

  1. On base: assign a fresh system wallet to dlp, then delegate_with_actions(payer, wallet, None, DelegateArgs { validator: <ER identity>, .. }, [action]), where action is any instruction that fails at execution (we use an SPL transfer larger than the source balance).
  2. Read the wallet on the ER. The ER clones it and runs the action.
  3. Wait for the wallet's owner on base to return to the system program.

Observed

ER log:

WARN magicblock_chainlink::chainlink::fetch_cloner: Post-delegation actions could not be satisfied; undelegating pubkey=BK91x… error=ClonerError(FailedToCloneRegularAccount(…, Engine("transaction execution failed: Error processing Instruction 6: custom program error: 0x1")))
ERROR execute{intent_id=8}: … Failed to execute intent bundle intent_id=8 error=FailedToFinalizeError { err: InternalError(MagicBlockRpcClientError(SentTransactionError(InstructionError(2, Custom(0)), 263axv…))), commit_signature: None, finalize_signature: Some(263axv…) }
WARN execute{intent_id=8}: … Intent execution resulted in stuck accounts stuck_accounts=Some([BK91x…])

Committor DB, table commit_status, row for the intent:

commit_type=EmptyAccount commit_strategy=StateArgs undelegate=1 data=None lamports=2000000000
delegated_account_owner=MagicRootDRJ5atQjSJUxFjXzjeZXMADHUDznbk22gy
commit_status=FailedProcess retries_count=0

The delegation record on base says owner = 11111111111111111111111111111111. The base transaction is [cu_limit, cu_price, commit_state, finalize, undelegate]; index 2 is commit_state.

Expected

The wallet's owner on base returns to the system program, as it did on master.

Root cause

  1. magicblock-chainlink/src/cloner/mod.rs:127, undelegation_action, builds a generic MagicBlockInstruction::ScheduleIntentBundle. The engine runs it as a MagicRootInstruction::PostFinalize action, so the Magic program sees a CPI from MagicRoot.
  2. programs/magicblock/src/magic_scheduled_base_intent.rs:601 calls CommittedAccount::from_account_shared(pubkey, &account, context.parent_program_id) with parent_program_id = Some(MagicRoot).
  3. magicblock-core/src/intent/types.rs:57: account.owner = parent_program_id.unwrap_or(account.owner); sets the owner to MagicRoot.
  4. magicblock-committor-service/src/tasks/commit_task.rs:57 passes committed_account.account.owner to dlp_api::instruction_builder::commit_state, which derives the program-config PDA from it.
  5. dlp derives the program-config PDA from delegation_record.owner (src/processor/fast/commit_state.rs:238). dlp-api/src/requires.rs:604 returns DlpError::InvalidAuthority (0) on mismatch.

Impact

Any delegation whose actions fail leaves the account under dlp on base, and the user cannot recover it without the validator key. The committor's error mapper has no case for Custom(0) on a commit task, so there is no retry, and the startup replay reuses the stored MagicRoot owner and fails the same way.

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions