Transaction-Ordering Dependency: How can it hamper a smart contract?

by ImmuneBytes

Race Conditions are one such situation that can have tremendous impacts on smart contracts and Transaction-Ordering Attacks are a common attack vector. 

We are back with yet another vulnerability that is often left unnoticed while deploying a smart contract, Transaction-Ordering Dependency. Make sure to check out the other parts in the series wherein we talk about Stack Size Limit, Integer Overflow and Underflow, and many other bugs that can prove lethal to smart contracts.

As we all know, a block includes a set of transactions that it executes, hence the blockchain state is updated several times in each epoch. Consider a scenario where the blockchain is in a state and the new block includes two transactions, invoking the same contract. In a scenario such as this one, users can have uncertain knowledge of which state the contract is at when their invocation is executed. Hence, a discrepancy occurs between the state of the contract that users may intend to invoke and the actual state when their corresponding execution happens. 

Only the miner who mines the block can decide the order of these transactions, consequently the order of updates. As a result, the final state of a contract depends on how the miner orders the transactions invoking it. Such contracts are called transaction-ordering dependent (or TOD) contracts.

But what’s the problem with TOD contracts?

It may be not obvious why having dependence on transaction order is problematic for smart contracts but the reasons are twofold. 

Let’s take a look at an example of a smart contract with a transaction-ordering dependency:

contract MarketPlace { 

uint public price; 

uint public stock ; 

/…/ 

function updatePrice ( uint _price ){

if ( msg. sender == owner ) 

price = _price ;  

function buy ( uint quant ) returns ( uint ) { 

if ( msg. value < quant * price || quant > stock ) 

throw ; 

stock -= quant ; 

 /…/ 

}

 

}

First, even a benign invocation to the contract may result in an unexpected result if there are concurrent invocations. Second, a malicious user can exploit such contracts to gain more profits, even steal users’ money.

This problem becomes more significant if the contract serves as a DeFi exchange or marketplace. In such contracts, sellers frequently update the price, and users send their orders to buy some assets. Depending on the transaction ordering, users’ buy requests may or may not go through. Even worse, buyers may have to pay much higher than the observed price when they issue the buy requests.

Bancor: A Real-life example of a TOD bug

A prominent example of a contract with a TOD vulnerability is Bancor. Bancor is a protocol for trading and pricing Ethereum ERC-20 tokens, as well as the eponymous token, abbreviated as BNT, with the current market cap rank of 120.

Bancor, an ICO that spectacularly raised over $150M in funding over a few minutes, was vulnerable to TOD. It was pointed out by a team of researchers that miners would be able to front-run any transactions on Bancor since miners are free to re-order transactions within a block they’ve mined. Any user running a full-node Ethereum client can spot a pending transaction and insert their transaction in front of it by paying more per gas. 

Surprisingly, the vulnerability does not seem to have been exploited so far and the team at Bancor claims that it’s been taken care of.

How can we fix it?

A possible solution to race conditions like these is by submitting information in exchange for a reward. This is termed as commit reveal hash scheme. 

Instead of conforming to the answer, the miner who has the answer submits the hash, where salt is a number of their choosing. The contract stores this hash and the sender’s address. To claim the reward the sender then submits a transaction with the salt, and answer. The contract hashes and checks the hash produced against the stored hash, if the two hash matches the contract then the reward is released.

This is ImmuneBytes take on the Transaction Ordering Dependency bug along with its real-world implementation to show you how it troubles smart contracts. Connect with our team of security professionals to get your smart contract free of any vulnerabilities and loopholes such as this one.

Tune in next Thursday for Part-VII of this series wherein we discuss the Delegate Call Return Value in smart contracts.

Spread the love

You may also like