  Since the emergence of Ethereum, blockchain-based decentralized applications
(DApps) have become increasingly popular and important. To balance the
security, performance, and costs, a DApp typically consists of two layers: an
on-chain layer to execute transactions and store crucial data on the blockchain
and an off-chain layer to interact with users. A DApp needs to synchronize its
off-chain layer with the on-chain layer proactively. Otherwise, the
inconsistent data in the off-chain layer could mislead users and cause
undesirable consequences, e.g., loss of transaction fees. However, transactions
sent to the blockchain are not guaranteed to be executed and could even be
reversed after execution due to chain reorganization. Such non-determinism in
the transaction execution is unique to blockchain. DApp developers may fail to
perform the on-chain-off-chain synchronization accurately due to their lack of
familiarity with the complex transaction lifecycle. In this work, we
investigate the challenges of synchronizing on-chain and off-chain data in
Ethereum-based DApps. We present two types of bugs that could result in
inconsistencies between the on-chain and off-chain layers. To help detect such
on-chain-off-chain synchronization bugs, we introduce a state transition model
to guide the testing of DApps and propose two effective oracles to facilitate
the automatic identification of bugs. We build the first testing framework,
DArcher, to detect on-chain-off-chain synchronization bugs in DApps. We have
evaluated DArcher on 11 popular real-world DApps. DArcher achieves high
precision (99.3%), recall (87.6%), and accuracy (89.4%) in bug detection and
significantly outperforms the baseline methods. It has found 15 real bugs in
the 11 DApps. So far, six of the 15 bugs have been confirmed by the developers,
and three have been fixed. These promising results demonstrate the usefulness
of DArcher.
