Skip to content

WIP Use safe transfers#228

Draft
naddison36 wants to merge 1 commit into
nicka/withdraw-on-swapfrom
nicka/safe-transfers
Draft

WIP Use safe transfers#228
naddison36 wants to merge 1 commit into
nicka/withdraw-on-swapfrom
nicka/safe-transfers

Conversation

@naddison36
Copy link
Copy Markdown
Collaborator

@naddison36 naddison36 commented May 14, 2026

Summary

Fix unchecked ERC-20 boolean return values across the shared ARM implementation and asset adapters.

This updates ARM and adapter token interactions to use OpenZeppelin SafeERC20, so transfer, transferFrom, and approve calls that return false now revert instead of letting execution continue after a failed token operation.

Changes

  • Use safeTransfer / safeTransferFrom for token movements in AbstractARM
  • Use forceApprove for ARM/adaptor approval paths
  • Apply the same SafeERC20 handling across all adapters under src/contracts/adapters/
  • Add a configurable false-return ERC-20 mock
  • Add regression coverage for failed transfer/approval behavior across:
    • deposits
    • exact-input and exact-output swaps
    • redeem claims
    • fee collection
    • base asset approval
    • allocation approval
    • adapter request/claim flows
    • adapter constructor/initializer approvals

Verification

  • forge build
  • forge test --match-path test/unit/OriginARM/ERC20Safety.sol -vvv
  • forge test --match-path test/unit/OriginARM/WrappedOriginAssetAdapter.sol -vvv
  • forge test --match-path test/unit/OriginARM/Deposit.sol -vvv
  • forge test --match-path test/unit/OriginARM/CollectFees.sol -vvv
  • forge test

Full suite result: 421 passed, 0 failed, 7 skipped.

Contract Size

Production ARM/adapters remain under the EIP-170 runtime limit, but headroom is tight:

  • EtherFiARM: 24,550 B, 26 B margin
  • LidoARM: 24,458 B, 118 B margin
  • EthenaARM: 23,935 B, 641 B margin
  • OriginARM: 23,606 B, 970 B margin

Existing Asset Behavior

None of the currently configured ARM assets are known to return false on failed ERC-20 transfers in normal operation.

The mainnet ARM asset set is:

  • OETH ARM: WETH, OETH, wOETH
  • Lido ARM: WETH, stETH, wstETH
  • EtherFi ARM: WETH, eETH, weETH
  • Ethena ARM: USDe, sUSDe

For the most relevant edge case, canonical mainnet stETH appears to be true-or-revert: transfer and transferFrom call internal transfer logic and return true after success, while invalid recipients, paused state, insufficient balance, or insufficient allowance revert.

So this change is primarily defensive hardening and ERC-20 integration hygiene rather than a fix for a known currently configured asset that returns false. It prevents future or misconfigured supported assets from minting shares, completing swaps, recording claims, or queueing adapter redemptions after a failed token operation.

@naddison36 naddison36 changed the title Use safe transfers WIP Use safe transfers May 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant