Nomadic Labs
Nomadic Labs
A technical description of the Dexter flaw

In this technical blog post, we detail the flaw found in the Dexter contract and the exploit used to “white-knight” the funds in those contracts.

Background

The Dexter contract contains several entrypoints allowing users to perform various operations, such as adding and removing liquidity, or converting tokens to tez back and forth. The exact interface is given by the type of the contract’s parameter:

parameter (or
            (or
              (or
                (pair %approve (address :spender)
                               (pair (nat :allowance) (nat :currentAllowance)))
                (pair %addLiquidity (pair (address :owner) (nat :minLqtMinted))
                                    (pair (nat :maxTokensDeposited)
                                          (timestamp :deadline))))
              (or
                (pair %removeLiquidity
                  (pair (address :owner) (pair (address :to) (nat :lqtBurned)))
                  (pair (mutez :minXtzWithdrawn)
                        (pair (nat :minTokensWithdrawn) (timestamp :deadline))))
                (or
                  (pair %xtzToToken (address :to)
                                    (pair (nat :minTokensBought) (timestamp :deadline)))
                  (pair %tokenToXtz (pair (address :owner) (address :to))
                                    (pair (nat :tokensSold)
                                          (pair (mutez :minXtzBought)
                                                (timestamp :deadline)))))))
            (or
              (or
                (pair %tokenToToken
                  (pair (address :outputDexterContract)
                        (pair (nat :minTokensBought) (address :owner)))
                  (pair (address :to) (pair (nat :tokensSold) (timestamp :deadline))))
                (or (key_hash %updateTokenPool) (nat %updateTokenPoolInternal)))
              (or (pair %setBaker (option key_hash) bool)
                  (or (address %setManager) (unit %default)))));

Of particular interest is the tokenToXtz entrypoint, which allows the swapping of tokens for tez. In Tezos, entrypoints are represented as different cases of a single sum type representing the expected parameter. The type for tokenToXtz is given as

(pair %tokenToXtz (pair (address :owner) (address :to))
                                    (pair (nat :tokensSold)
                                          (pair (mutez :minXtzBought)
                                                (timestamp :deadline)))))))

This means that the entrypoint expects a record with the following fields

  • deadline : the time until which the transaction requested is valid
  • minXtzBought : the minimum amount of tez requested. If the tokens were to be swapped for fewer tez, the transaction be considered invalid, protecting the seller against excessive slippage
  • tokensSold : the number of tokens the seller desires to sell
  • to : the address where the tez proceeds are to be sent
  • owner : the owner of the tokens being sold

When the Dexter contract receives requests, it performs a series of computations to determine how many tez should be sold and, ultimately, emits two operations. One which sends tez to the “to” field, and the other, directed at the FA1.2 token contract, which request a transfer of tokens from the owner to the Dexter contract itself. If any of these transactions fail, the whole transaction fails.

An FA1.2 transfer is valid if and only if the contract calling the FA1.2 contract owns the tokens being transferred, or if it is present in the allowance list for the owner of the tokens. This is a pattern found in ERC20 as well.

When Dexter users sell tokens to Dexter, they typically first make a temporary allowance in the FA1.2 contract to allow Dexter to access their funds.

Flaw

The presence of an owner field in tokenToXtz raises two problems. First, it means a user is able to spend the token of anyone who has an open allowance to Dexter. While it is possible to recommend that allowances only be set temporarily and be reset to 0 after every interaction with the contract, this was not, in fact, done, and we found that several liquidity providers had small dangling allowances left after adding liquidity.

More problematic is the fact that the owner field could simply be set to the Dexter contract’s address itself. Since the caller of an FA1.2 contract is always allowed to spend its own funds, this means that the Dexter contract could be instructed to dispense tez by sending itself its own tokens. Self-transfers are normal, and even required in the FA2 standard.

Dexter implements a constant formula market maker which attempts to maintain constant (before fees) the product of the quantity of the two assets it holds. By asking the Dexter contract to send itself its entire token balance, it’s possible to collect (before fees) roughly half of its tez balance.

The presence of an owner field in tokenToXtz was unnecessary, and its only safe value would be SENDER, which renders it useless as a parameter.

Conclusion

It is important for authors of smart contracts to consider and test edge conditions of all sorts on all possible calls. This is especially true in situations where a contract can be told to transfer value to or from a third party. Creators of contracts should strongly consider avoiding such facilities entirely when they are not critical to the function of a contract. When providing such facilities, it is vital to consider whether edge cases might result in unexpected behavior.


Dexter Flaw Discovered; Funds are Safe

TL;DR: A flaw was found in the camlCase’s Dexter contract. The funds have been removed from the contract and returned to their original holders. A high level explanation follows; technical details of the Dexter flaw will be described in a separate post to come. As many of you know, we have been working on a new Tezos upgrade proposal. This proposal, if accepted, will change the calling convention from breadth first ordering to depth first ordering. In...

Read More
Edo, the latest Tezos upgrade, is LIVE

This is a joint announcement from Nomadic Labs, Marigold, and DaiLambda. On 13 February 2021, the Tezos blockchain successfully upgraded by adopting Edo at block 1,343,489. Jointly developed by Nomadic Labs, Marigold, DaiLambda, and Metastate, Edo is the fifth Tezos upgrade in the span of two years, and follows the Delphi upgrade of three months ago. The Tezos blockchain currently allows protocol upgrades every several months, and we intend for the foreseeable future to take advantage of...

Read More
IMPORTANT: Critical Patch to Tickets in Edo

We have discovered a critical bug within the new Tickets functionality in Edo. Several mechanisms were considered to mitigate this problem; none were ultimately found to be satisfactory. We have therefore taken the step of producing and releasing version 8.2 of the Tezos node that includes a patched version of the Edo protocol that differs by only a few lines of code. Nodes running 8.2 will automatically adopt the patched version rather than the original version of Edo when it activates on February 13th, 2021, around...

Read More
A look ahead to Tenderbake

We’re working on changing the Tezos consensus algorithm from the current Emmy+ algorithm, to a new algorithm called Tenderbake. We’d like to discuss this development, and explain why we’re considering it, and what advantages it will bring. Tenderbake and Emmy+ belong to different algorithm families: Emmy+ is a Nakamoto style algorithm, whereas Tenderbake is a BFT-style algorithm. So moving to Tenderbake would be a significant development on the Tezos network. We made every effort to keep this blog post self-contained, but just in...

Read More
POPL 2021 retrospective

A short summary of our experience at POPL, CPP and CoqPL this year.

About POPL (Symposium on Principles of Programming Languages) POPL 2021 — the 48th ACM SIGPLAN Symposium on Principles of Programming Languages — is a premier annual conference event of the Programming Languages research community. POPL consists of a main conference, and many colocated events, which together present the latest and greatest research in (amongst other topics): programming languages theory, formal verification, type systems, and functional programming — all subjects which are dear to...

Read More
Introducing mockup mode for tezos-client

Presenting tezos-client’s new mockup mode feature

We are pleased to announce that the tezos-client binary has a new feature aimed at contract and tool developers alike: the mockup mode. Mockup mode allows easy prototyping of Tezos applications and smart contracts locally. By local we mean: The relevant data files sit in a directory on your computer’s local filesystem. These files are a lightweight emulation of the internal state of a Tezos single-node network. Thus, networking communications infrastructure that a node would be wrapped...

Read More
Announcing the Edo Release!

This is a joint announcement from Nomadic Labs, Marigold, and Metastate. A couple of weeks ago, we were proud to see the “Delphi” upgrade to the Tezos protocol go live. This week, we are proud to announce our latest protocol upgrade proposal, “Edo”. As usual, Edo’s true name is its hash, which is PtEdoTezd3RHSC31mpxxo1npxFjoWWcFgQtxapi51Z8TLu6v6Uq. Why is Edo being proposed when Delphi has only been in place for a short while? Although Delphi went live on November 12th,...

Read More
Announcing Ebetanet, the Edo Preview Network!

We have just spawned a test network for a beta version of the Edo protocol, which we plan to propose as the next (008) Tezos protocol upgrade. The code running on the test network is our release candidate for Edo. We anticipate that the beta period will last only one to two weeks before our proposal is final. Please participate by testing it now! We plan to replace this test network with Edonet, the successor of Delphinet, once we...

Read More
Cortez End of Support

In a context where Nomadic Labs aims to concentrate on its high value activities, we plan to refocus our efforts on projects and tools that are directly related to the heart of Tezos and its economic protocol. As a result, Nomadic Labs decided to discontinue its support and maintenance of both the Android and iOS versions of the Tezos mobile wallet, Cortez. After a grace period running from now to 15 February 2021, Nomadic Labs will no longer...

Read More