# transfer_share_and_rewards allows for self transfer

Acala rewards library's transfer_share_and_rewards lacks a self-transfer check, letting a user credit themselves shares and rewards repeatedly, inflating balances.

- Payout: Contest reward
- Severity: high
- Program: Acala Network
- Credited: ZanyBonzy
- Disclosed: 2024-05-02
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2024-03-acala-findings/issues/16
- Library page: https://bugbountylibrary.com/r/c4%3A2024-03-acala%3AH-01
- Tags: domain:web3 impact:funds-loss impact:integrity kind:contest platform:code4rena sev:high tech:rust technique:source-review vuln:accounting-error vuln:business-logic

**Target:** ORML rewards pallet transfer_share_and_rewards
**Root cause:** transfer_share_and_rewards does not reject who == other, so the debit and credit both apply to the same account, netting a gain in shares and withdrawn rewards.
**Steps:**
1. Set up pool with BOB holding 100 shares and accumulated rewards.
2. ALICE adds 100 shares.
3. Call `transfer_share_and_rewards(&ALICE, &DOT_POOL, 90, &ALICE)`; ALICE balance becomes 190 shares / 190 rewards.
4. Repeat with 180 to reach 370.
5. Transfer 70 to BOB, then BOB self-transfers 100 twice to inflate his own balance.
**How found:** Code review of the rewards library transfer function, noticing no guard against sender==recipient, then writing a Rust test to confirm balance inflation.
**Exploitation:** Any share holder calls transfer_share_and_rewards with recipient equal to sender, repeatedly increasing their own share and reward accounting; not currently wired into in-scope contracts.
**Insight:** In share/reward accounting, always test self-transfer and zero-value edge cases: a debit+credit to the same account can net positive if the credit path reads pre-debit state.
