tl;dr
đź’Ł The contract has a vulnerability with bidding. You need to cancel any bids (cancelBid
) you have created on Number Board or your bid payment can be stolen. If you own any Number Board cards, do not accept any bids or your Number Board card may be stolen. You can continue using the existing Number Board without any bid functions or wait to upgrade your Number Board cards using an upcoming ERC-721 upgrade contract. The original developer is still active on this project.
Background
Number Board is a 2017 non-fungible smart contract which allows free claim of any “number” and includes marketplace functionality to trade claimed number.
Originally deployed in November 16, 2017 at transaction 0x186bfad6b5f5d2711c4a9a2f0134bee0554f9f34af139b1743e0f3b2c6d5a99b
, this contract includes a built-in marketplace.
The contract is deployed at 0x9249133819102b2ed31680468c8c67F6Fe9E7505
.
This marketplace is vulnerable to two serious attacks. A workaround is provided.
Intended functionality
Several functions are included with intent for a seller to initiate transactions:
Seller function | Buyer function |
---|---|
placeBuyNowOffer |
acceptBuyNowOffer |
cancelBuyNowOffer |
 |
And separately, other functions are included with intent for a buyer to initiate transactions:
Buyer function | Seller function |
---|---|
⚠️ placeNewBid |
⚠️ acceptBid |
cancelBid |
 |
Inherently there is no design flaw for a six-function marketplace using these primatives. However the implementation makes fatal errors that allow payment theft.
Vulnerability 1: atomic bid rugpulling
This vulnerability is the easiest to explain but it is the hardest to implement, so a demonstration on Ethereum Mainnet is not provided.
The vulnerable situation is as follows. A prospective buyer wishes to purchase Number Board card X for a price of 1 Ether. The bidder has placed a bid using placeNewBid
.
The owner wishes to execute this transaction on these terms and uses acceptBid
.
However in the meantime and unbeknownst to the owner, a pirate jumps in and executes these commands in quick succession:
placeNewBid
with a price of 1.1 EthercancelBid
placeNewBid
with a price of 0.001 Ether
The end result is that the pirate receives the card X and the previous owner receives 0.001 Ether instead of the expected 1 Ether.
Executing this kind of rapid insertion of sequential orders requires access to an Ethereum mining node, a MEV pool, good luck and/or a keen insight into exactly when the owner might execute the acceptBid
order. This may be especially easy if the owner uses a low gas/total gas/priority gas setting.
Recommendation for callers of the contract:
- ⚠️ Never call the
acceptBid
function. - Consider to upgrade your Number Board cards to ERC-721 tokens.
Vulnerability 2: amplified offer sandwich
Here a buyer is interested in purchasing a Number Board card (let’s say 7887) for a certain amount (lets say 0.05 Ether).
This one is harder to explain because it is not intuitive because it depends on an implementation detail. Let’s just review an example of what might happen after this buyer makes a bid…
- Prospective buyer calls
placeNewBid
for 0.05 Ether - Owner calls
placeBuyNowOffer
for 0.01 Ether - Owner calls
acceptBid
to get the 0.05 Ether minus fees - Owner calls
acceptBuyNowOffer
to get the card back at low price - Owner calls
withdrawEarnings
to get payment back - Prospective buyer calls
withdrawEarnings
for partial tuition reimbursement
And summarizing the outcome:
- The prospective buyer paid all their bid value and received some minor refund payment
- The owner received the payment (minus 1% fee)
- The owner still has the Number Board card
Of course that is very bad.
It is easy to execute this strategy as the Owner. One can easily enter transactions in quick succession.
⚠️ If executing this strategy you are also at risk of being counterattacked. However that counterattack may be difficult to execute, again see notes about gas, mining nodes etc. above.
Recommendations for contract design
Rugpulling and pirates need to be considered for all marketplace functions in all smart cotracts.
Rugpulling is also called “phantom liquidity” and “quote fading” in the context of regulated exchanges.
Pirates are also called “miner extracted value” (MEV).
Recommendations for Number Board owner
It is not possible to stop people from interacting with the contract. But the website should be updated to remove all calls to the placeNewBid
and acceptBid
functions. A note should be added to the website to raise awareness of this issue.
Disclosure timeline
- 2021-09-27 Discovered
- 2021-09-27 Disclosed to project owner
- 2021-09-27 Notified project participants to consider cancelling bids
- 2021-09-27 Notified project participants to cancel bids now, write up coming Wednesday at Noon New York time
- 2021-09-29 Publicly disclosed on Privacy Log
▧
Comments
There are no comments yet.
Please discuss this topic anywhere and let me know any great comments or media coverage I should link here.