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
Arc Testnet rejects any transaction where the sender and recipient are the same address (from == to) and the transaction carries non-empty data. The error returned is:
External transactions to internal accounts cannot include data
This is enforced at the consensus layer, not by the EVM or a smart contract. It cannot be worked around by adjusting gas, fee fields, or transaction type.
Environment
Network: Arc Testnet (Chain ID: 5042002)
Trigger: any eth_sendTransaction or wallet_sendCalls where from === to and data.length > 0
Tools affected: MetaMask, viem, ethers.js, cast — any library that submits the raw transaction
Reproduction
// Attempt to send a self-call with data (e.g. to attach an on-chain memo)consttx=awaitwindow.ethereum.request({method: "eth_sendTransaction",params: [{from: "0xYourAddress",to: "0xYourAddress",// same as fromdata: "0x48656c6c6f",// any non-empty calldatavalue: "0x0",gas: "0x7530",}],});// → MetaMask submits, Arc node rejects:// "External transactions to internal accounts cannot include data"
Note: the same call with data: "0x" (empty) succeeds — it is the combination of from == toand non-empty data that is rejected.
Impact
This silently breaks a common pattern used by dApps to attach on-chain memos to transactions:
Self-call memo pattern — encode a UTF-8 string as calldata, send to self. Widely used on Ethereum mainnet and other EVMs. Completely blocked on Arc Testnet.
Consequence for the Arc Memo precompile — the Memo precompile (0x5294E9927c3306DcBaDb03fe70b92e01cCede505) is the only supported on-chain memo path, but it has its own gas-estimation bug (see issue #189). The self-call restriction means there is currently no simple, estimation-compatible fallback.
Discovered during Batch Transfer integration
We hit this while building Arc Stablecoin DApp, specifically on the Batch Transfer feature. The original design appended an on-chain text memo by sending a self-call with the memo encoded as calldata — a standard EVM pattern:
// Original design — fails on Arcawaitwindow.ethereum.request({method: "eth_sendTransaction",params: [{from: userAddress,to: userAddress,data: toHex(newTextEncoder().encode(memoText)),}],});// → "External transactions to internal accounts cannot include data"
Workaround we used: Added a string calldata memo parameter directly to batchTransfer(). The memo is emitted in the BatchExecuted event and stored in the transaction log in the same confirmation — no separate transaction or self-call needed:
This restriction is distinct from the gas-estimation bug in #189:
Scenario
Error
Stage
Workaround
callWithMemo via viem / ethers
Gas estimation fails
RPC simulation
Pass explicit gas: override
Self-call with non-empty data (from == to)
Consensus rejection
Block inclusion
Cannot use self-calls — embed memo differently
The gas: override that fixes #189 does not help here — the transaction is rejected at block inclusion, not during estimation.
Suggested documentation / guidance
Document the from == to + data restriction explicitly in Arc developer docs — the error message is opaque and this behaviour differs from Ethereum mainnet.
For dApps that own their contract: embedding memo as a function parameter and emitting it in an event is a zero-extra-confirmation alternative that avoids both issues entirely.
References
Related: issue #189 — callWithMemo gas estimation failure
Related: PR #182 — Arc Transaction Memo integration example
Working implementation: BatchTransfer.sol on Arc Testnet (source-verified)
Summary
Arc Testnet rejects any transaction where the sender and recipient are the same address (
from == to) and the transaction carries non-emptydata. The error returned is:This is enforced at the consensus layer, not by the EVM or a smart contract. It cannot be worked around by adjusting gas, fee fields, or transaction type.
Environment
eth_sendTransactionorwallet_sendCallswherefrom === toanddata.length > 0Reproduction
Impact
This silently breaks a common pattern used by dApps to attach on-chain memos to transactions:
0x5294E9927c3306DcBaDb03fe70b92e01cCede505) is the only supported on-chain memo path, but it has its own gas-estimation bug (see issue #189). The self-call restriction means there is currently no simple, estimation-compatible fallback.Discovered during Batch Transfer integration
We hit this while building Arc Stablecoin DApp, specifically on the Batch Transfer feature. The original design appended an on-chain text memo by sending a self-call with the memo encoded as calldata — a standard EVM pattern:
Workaround we used: Added a
string calldata memoparameter directly tobatchTransfer(). The memo is emitted in theBatchExecutedevent and stored in the transaction log in the same confirmation — no separate transaction or self-call needed:Deployed and source-verified on ArcScan:
0x76d5dd51ad28D607cD8804dc5230cAE93403eD3dLive example — memo
"Invoice MR"decoded by name in the Logs tab on ArcScan:https://testnet.arcscan.app/tx/0xacc2bc5a96ecac286549132303e664f3ade81969c26e788c814798f20f13b429?tab=logs
Comparison with issue #189
This restriction is distinct from the gas-estimation bug in #189:
callWithMemovia viem / ethersgas:overridedata(from == to)The
gas:override that fixes #189 does not help here — the transaction is rejected at block inclusion, not during estimation.Suggested documentation / guidance
from == to + datarestriction explicitly in Arc developer docs — the error message is opaque and this behaviour differs from Ethereum mainnet.0x5294...) as the supported alternative, with a note about the gas-estimation workaround (callWithMemo reverts during gas estimation (eth_call) but succeeds with direct signed transaction #189).References
callWithMemogas estimation failureBatchTransfer.solon Arc Testnet (source-verified)