I want to build an oracle similar to OmniBridge for xDai or Arbitrary Message Bridge but I am worried about how to make it secure.

It would seem such an oracle should be reliable, as long as there is a way to take the hash of a transaction and prove that it was included in a block, which in turn was mined on the "main blockchain". (That last part is subjective, but as long as we can prove enough block difficulty after the transaction, the smart contract calling the oracle can be satisfied). The components I need to verify all this are:

  1. The Merkle Branch (or some other proof) that the transaction was mined in its Block

  2. Some way to verify how many blocks were "legitimately" mined until we get to the hash of the "latest/top" block (which the oracle would just get from the blockchain nodes).

  3. The person will provide the actual transaction parameters, and the transaction's hash would have to be computed again by the smart contract, to make sure it is the right hash.

Is 1, 2, 3 even possible? That's the question!

The idea is to "cash out" X amount of FOO tokens which were sent to a smart contract on the Ethereum mainnet and locked there. For example if someone sends corresponding X amount of xFOO tokens on the xDai chain, and this transaction is "confirmed" after a few blocks, then the person can call a method on the smart contract, and it will release X tokens to the same wallet EOA address that sent them.

Security analysis: Presumably, under a large enough blockchain like xDai, whether it's PoW or PoS, it should be secure, but if X is large enough, someone might want to fool the oracle network by mining more fake blocks on top and then "proving" that the transaction happened. I guess they can't really fool the oracle, though, because the ERC1677 token contract on xDai would roll back any transaction that didn't have enough balance. They'd have to fork the entire xDai network and mess up a lot in order to fake a transaction that violates the smart contract logic.

  • I do not understand well, do you want the items 1,2,3 to run inside a smart contract? Or are you talking about the entire system of the Oracle, which will also include geth node and related javascript scripts to manage it?
    – Nulik
    Commented Feb 2, 2021 at 22:45
  • if a transaction is inside a block then it was mined, you can be 100% sure about it, as long as you wait for enough confirmations, given that chain reorg happens twice or once a day
    – Nulik
    Commented Feb 2, 2021 at 22:46
  • But how can I verify the proof onchain inside the smart contract in the ethereum mainnet? 1,2,3 seem to require some heavy duty functions, like generating the hash of the transactions USING SOLIDITY, same as geth does? Commented Feb 3, 2021 at 2:43

1 Answer 1


But how can I verify the proof onchain inside the smart contract in the ethereum mainnet? 1,2,3 seem to require some heavy duty functions

Inside smart contract it is not possible. There are hundreds of contract calls executed per block in the EVM (Ethereum Virtual Machine) and there is no room for complex logic like you are requesting. The only "conectivity" with the blockchain the EVM provides are 2 types of objects:

  1. Block context
  2. Transaction context

These are defined in the core/vm/evm.go and here is the definition:

// BlockContext provides the EVM with auxiliary information. Once provided
// it shouldn't be modified.
type BlockContext struct {
    // CanTransfer returns whether the account contains
    // sufficient ether to transfer the value
    CanTransfer CanTransferFunc
    // Transfer transfers ether from one account to the other
    Transfer TransferFunc
    // GetHash returns the hash corresponding to n
    GetHash GetHashFunc

    // Block information
    Coinbase    common.Address // Provides information for COINBASE
    GasLimit    uint64         // Provides information for GASLIMIT
    BlockNumber *big.Int       // Provides information for NUMBER
    Time        *big.Int       // Provides information for TIME
    Difficulty  *big.Int       // Provides information for DIFFICULTY

// TxContext provides the EVM with information about a transaction.
// All fields can change between transactions.
type TxContext struct {
    // Message information
    Origin   common.Address // Provides information for ORIGIN
    GasPrice *big.Int       // Provides information for GASPRICE


As you can see, you can only get the Sender's address (Origin) and GasPrice from the transaction context. For the Block you can get the miner's address, block number, the gas limit of the Block, time and difficulty. That's it.

The state trie (Merkle Patricia) , the one that stores the information about accounts is not accessible from the contract in a form that you want. In fact, the nodes of Merkle Patricia Trie are built from hashes of accounts because the team was worried about security , and wanted to ensure that the contract would not be able to access the nodes of the trie deterministically, so hash of the account address makes the positioning of your account in the trie in a completely random way. I mean, you are requesting a feature that Ethereum foundation explicitly prohibited you to have. It exposes the trie for DDoS attacks. (personally I don't see any security issue here, but well, it was done the way it is done)

The only way you can implement what you want is by defining the corresponding variables in the contract, and updating them yourself (like block hashes, proofs, etc) Other people would have to trust your data.

Long time ago, I also was thinking on how to connect two chains automatically, but didn't find any way to make it 100% without human intervention or authoritative entities. The problem is this:

  • To prove something on Ethereum Main Net you need to have the full trie and all the block headers from the Genesis block. There is no way a contract can do it, it is about 500 GB of data and it needs to be ran every block.
  • To prove that Ethereum Main Net was modified from inside another chain you need to observe the events at Ethereum Main Net, and this also requires having all block headers and the full state trie.
  • Therefore, the only way you can make communication between two chains is if you are standing in a third point, and are observing two different blockchains.

Absolute proofs are computationally expensive, but trust is cheap, that's why everybody is using trusted entities and rely on validators of some sort.

  • Great answer. Is there any way to maybe “summarize” the main elements of the proof in a short proof that can be checked onchain? Commented Feb 9, 2021 at 3:20
  • if I am remembering it correctly the light client does "short proofs" , but a full node has to be a server for light client, so, same thing, you have to be in posession of all the data
    – Nulik
    Commented Feb 9, 2021 at 15:32
  • And can any of these short proofs be verified onchain in the mainnet? Commented Feb 11, 2021 at 17:58
  • yep, the function keccak256 hash is available in the EVM, so the same operations can be reproduced inside the contract, but the fields (storage root, nonce, balance, account address) have to be provided on the input to the contract. and the guy who is going to provide this input must be trusted
    – Nulik
    Commented Feb 11, 2021 at 20:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.