On Sep. 7, 2020, Jong Seok Park posted in this medium post describing a delegation double spending bug in the governance subsystem of SushiSwap. Upon receiving the notice, PeckShield researchers immediately analyzed the vulnerability and came up with this blog to further elaborate the technical details.

Figure 1: A Summary Of Sybil Attacks


The bug is introduced by the SushiToken contract that fails to accompany _moveDelegates() with every transfer() or transferFrom() call. Because of that, this bug might be exploited by a bad actor to double-spend already delegated votes and launch the so-called Sybil attack to undermine the SushiSwap’s governance. For illustration, as shown in Figure 1, Bob can delegate his 100 SUSHIs’ votes to Charlie if he has a balance of 100 SUSHIs. Now, Charlie can cast his 100 SUSHIs’ votes because of the delegation. However, since the transfer() handler of SushiToken fails to apply the logic of moving delegates, Bob could transfer his 100 SUSHIs to his accomplice, Alice. And Alice could delegate the votes of 100 SUSHIs to Charlie again! This could repeat again and again by iterating the sending of 100 SUSHIs to Malice, Trudy, Linda, and Eva with all of them re-delegating the same batch of SUSHIs votes to Charlie. Eventually, Charlie can have the voting power of 100*N SUSHIs which actually is backed by 100 SUSHIs only.


We started with the analysis of the _delegate() helper routine that is invoked by
externally-facing functions, delegate() and delegateBySig(), in the SushiToken contract. As shown in Figure 2, the delegate() helper allows the delegator to move delegateBalance of SUSHIs voting power to delegatee. Note that delegateBalance is computed by the balance of SUSHIs owned by the delegator.

Figure 2: _delegate() in SushiToken Contract

Based on that, a bad actor could launch the Sybil attack to undermine the governance subsystem by following the steps below. Here we assume Bob has 100 SUSHIs and all others have 0 SUSHI before the attack is launched:

Action Charlie’s Voting Power Bob Alice Malice Trudy
Initial State 0 100 0 0 0
Bob delegates his 100 SUSHIs to Charlie 100 100 0 0 0
Bob transfers his 100 SUSHIs to Alice 100 0 100 0 0
Alice delegates her 100 SUSHIs to Charlie 200 0 100 0 0
Alice transfers her 100 SUSHIs to Malice 200 0 0 100 0
Malice delegates her 100 SUSHIs to Charlie 300 0 0 100 0
Malice transfers her 100 SUSHIs to Trudy 300 0 0 0 100
Trudy delegates her 100 SUSHIs to Charlie 400 0 0 0 100

As a result, Charlie could have 400 SUSHIs’ voting power even though there is only 100 SUSHIs involved. By creating a large, arbitrary number of new addresses during the Sybil attack, the malicious actor can effectively amplify the voting powers even with a small number of SUSHIs in the play.

Comparison With YAM The reason why Bob could launch the attack in SushiSwap is due to the lack of accompanying _moveDelegates() call in the transfer() and transferFrom() handlers of the SushiToken contract. Specifically, SushiToken leverages the OpenZeppelin’s ERC20 implementation that does not have the above add-on. As a counter-example of the governance implementation, the YAM token contract does perform _moveDelegates() in each transfer() or transferFrom().

Figure 3: transfer() in YAM Contract


Time Milestone
13:15:00 +UTC, Sep-7-2020 Park’s medium post released.
15:48:00 +UTC, Sep-7-2020 PeckShield’s report sent to SushiSwap team, including @SBF_Alameda.
15:59:59 +UTC, Sep-8-2020 PeckShield’s analysis blog published.

About Us

PeckShield Inc. is an industry leading blockchain security company with the goal of elevating the security, privacy, and usability of current blockchain ecosystem. For any business or media inquiries (including the need for smart contract auditing), please contact us at telegram, twitter, or email.


08 September 2020