# _sendToken implementation in Balancer.sol is wrong which will make the underlying erc20 be send to a random address and lost

Balancer.sol _sendToken used abi.encode instead of abi.encodePacked for Stargate dstOft address, so rebalanced ERC20s were sent to a truncated random address and lost.

- Payout: Contest reward
- Severity: high
- Program: Tapioca DAO
- Credited: Vagner
- Disclosed: 2023-11-16
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2023-07-tapioca-findings/issues/369
- Library page: https://bugbountylibrary.com/r/c4%3A2023-07-tapioca%3AH-55
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:high tech:evm tech:solidity technique:source-review vuln:accounting-error

**Target:** Balancer.sol _sendToken / Stargate router swap
**Root cause:** _sendToken passed abi.encode(dstOft) as the Stargate destination address instead of abi.encodePacked, so the 32-byte encoding's leading zeros caused the receiving Bridge to load only the low 20 bytes as toAddress.
**Steps:**
1. Call rebalance on Balancer.sol for a connected OFT and dstChainId.
2. Observe _sendToken builds the destination via `abi.encode(connectedOFTs[_oft][_dstChainId].dstOft)` (32 bytes) rather than `abi.encodePacked` (20 bytes).
3. Stargate router.swap forwards payload; destination Bridge.lzReceive assembly loads 20 bytes from payload offset, yielding a truncated address like `0x0000000000000000000000005b38Da6A701c5685`.
4. Tokens are swapped to that non-existent address; sgReceive fails and assets are lost.
**How found:** Compared _sendToken against _sendNative and Stargate docs; noticed _sendNative correctly uses abi.encodePacked while _sendToken uses abi.encode, then traced how Bridge.lzReceive assembly reads 20 bytes of payload.
**Exploitation:** Owner-triggered rebalance sends ERC20 to a truncated destination address derived from the leading zeros of abi.encode; the receiving Stargate Bridge loads 20 bytes and routes to a wrong address with no sgReceive, losing the funds.
**Insight:** When a protocol encodes an address for a cross-chain payload, diff every call site against the documented encoding; abi.encode vs abi.encodePacked on addresses silently shifts bytes and downstream assembly that slices fixed offsets will read the wrong address.
