
The Kwenta Token Migration
The swap interface for migrating your KWENTA tokens to SNX is now live. This migration unlocks opportunities to participate in the Synthetix system and DAO, where your SNX tokens can be staked and used to help govern the protocol. Follow the simple steps below to ensure a smooth transition and start vesting your tokens today. For more details about the unification with Synthetix, check out this blog.Key Details About Token VestingTokens began vesting on November 12th, even if you havenβt depo...

Kwenta x Synthetix: Next Steps
Following the unification announcement, weβre now entering the next phase of the transition. This stage focuses on streamlining token migration, refining incentives, and ensuring traders experience a smooth shift as Kwenta evolves into Synthetix Exchange.Social Media UpdatesKwentaβs community spaces are evolving to support this transition while ensuring traders and community members continue to have access to resources and support.Discord ChangesWhile most channels will be archived, key chann...

Kwenta x Synthetix: A Unified Future
Today marks a monumental step forward for both Kwenta and Synthetix. Following the approval of KIP-138 by the Kwenta community and SIP-411 by the Synthetix community, the two projects will now reunite under a single mission: to build the most powerful decentralized derivatives platform in DeFi.Why Was This Decision Made?This unification brings Kwenta full circle. Originally launched in 2021 as an independent protocol through SIP-179, Kwenta was designed to be a dedicated front end for Synthet...
Kwenta has been acquired by Synthetix. Please follow along at https://blog.synthetix.io/ Trading is live at https://exchange.synthetix.io/



The Kwenta Token Migration
The swap interface for migrating your KWENTA tokens to SNX is now live. This migration unlocks opportunities to participate in the Synthetix system and DAO, where your SNX tokens can be staked and used to help govern the protocol. Follow the simple steps below to ensure a smooth transition and start vesting your tokens today. For more details about the unification with Synthetix, check out this blog.Key Details About Token VestingTokens began vesting on November 12th, even if you havenβt depo...

Kwenta x Synthetix: Next Steps
Following the unification announcement, weβre now entering the next phase of the transition. This stage focuses on streamlining token migration, refining incentives, and ensuring traders experience a smooth shift as Kwenta evolves into Synthetix Exchange.Social Media UpdatesKwentaβs community spaces are evolving to support this transition while ensuring traders and community members continue to have access to resources and support.Discord ChangesWhile most channels will be archived, key chann...

Kwenta x Synthetix: A Unified Future
Today marks a monumental step forward for both Kwenta and Synthetix. Following the approval of KIP-138 by the Kwenta community and SIP-411 by the Synthetix community, the two projects will now reunite under a single mission: to build the most powerful decentralized derivatives platform in DeFi.Why Was This Decision Made?This unification brings Kwenta full circle. Originally launched in 2021 as an independent protocol through SIP-179, Kwenta was designed to be a dedicated front end for Synthet...
Kwenta has been acquired by Synthetix. Please follow along at https://blog.synthetix.io/ Trading is live at https://exchange.synthetix.io/
Share Dialog
Share Dialog

Subscribe to Synthetix Exchange

Subscribe to Synthetix Exchange
>1K subscribers
>1K subscribers
At 2 AM UTC Friday, July 14th, 2023, a potential vulnerability was discovered by Kwenta smart contract engineers in the set of StakingV2 contracts that put newly minted inflationary rewards at risk. This was later validated by a proof of concept (PoC) test case. Relevant parties were alerted and gathered. Swift action was taken by the Kwenta protocolDAO (pDAO) to pause the StakingV2 contracts to secure staker funds.
Analysis continued into the weekend, with auditors engaged, to fully understand the issue and prepare a potential rollback of the migration.
A decision to reverse the migration was made on Monday.
Thankfully, the launch of StakingV2 had only occurred a few hours prior, and the vulnerability was discovered internally before funds were at risk. As of this time, all funds are safe, and a reverse migration is taking place.
The vulnerability stems from the fact that StakingV1, when stake and unstake actions occur, does not alert the StakingV2 contract of these state changes.
The Staking contract works when an action (like stake/unstake) is performed, and the amount of reward tokens owed to you in the time (based on your stake) that has passed is recorded. Because StakingV1 actions do not alert StakingV2 properly, it's possible to lose all or extract more rewards than is deserved.
The migration process was halted because the bug could be encountered during the migration flow from StakingV1 to StakingV2. If a V1 staker begins accruing V2 rewards and then attempts to unstake from StakingV1 in order to migrate to StakingV2, all V2 accrued rewards (or rewards pertaining to the now unstaked "liquid" stake) are lost because the earned amount is not properly recorded on the V2 contract.
function test_Actual() public {
fundAccountAndStakeV1(user1, 10 ether);
vm.warp(block.timestamp + 1 weeks);
vm.prank(user1);
stakingRewardsV1.unstake(10 ether);
uint reward = stakingRewardsV2.rewards(user1);
assert(reward > 0);
}
Eventually, this issue revealed deeper issues within the StakingV2 contracts. For example, it is possible to manipulate the V1 stake function to generate more rewards than are deserved.
By increasing your V1 stake (potentially with a flashloan) before claiming rewards, your earned rewards can be manipulated because your previous staked amount isnβt properly accounted for on the V2 contract.
Therefore, when you go to claim your rewards, it will be based on your new staked balance * the time since the original stake event.
function test_Flash_Attack() public {
uint256 totalNewRewards = 100_000 ether;
fundAccountAndStakeV2(user1, 100 ether);
fundAccountAndStakeV2(user2, 100 ether);
addNewRewardsToStakingRewardsV2(totalNewRewards);
vm.warp(block.timestamp + 4 weeks);
// flash attack
uint256 fundsBorrwedViaFlashLoan = 100_000 ether;
fundAccountAndStakeV1(user3, fundsBorrwedViaFlashLoan);
vm.prank(user3);
stakingRewardsV2.getReward();
uint256 escrowedBalance = rewardEscrowV2.escrowedBalanceOf(user3);
// users claimed at least 99.8% of all the rewards
assertCloseTo(escrowedBalance, totalNewRewards, 200 ether);
// then user would pay back the flash loan
}
Kwenta has multiple security processes to prevent issues like these; however, there is always a non-zero chance of an incident. All new code undergoes thorough testing utilizing Foundry's testing suite. Kwenta Engineering makes use of unit, integration, fork tests, and extended testing tools like fuzz and invariant tests.
We enforce 80+% code coverage. The code is then reviewed internally by the Core Contributors (CCs) and then external auditors, such as our partners Macro and Omniscia, for vulnerabilities and potential edge cases. Lastly, post-launch, we set up monitoring tools (Tenderly alerts for invariants) and bug bounty programs to limit any potential vulnerabilities that may crop up in production.
In this case, the logic behind the Staking contracts during development was a misunderstanding. It was not enough to pull StakingV1 balances into the StakingV2 contract only when V2 balances were changed. Unfortunately, there were a few internal process failures that could have mitigated this issue.
StakingV2 is a large, intricate system with many new technical features and expected legacy support. Most of these changes were delivered as a monolithic pull request on Github, making it hard for the internal team to scrutinize every feature and modification. Secondly, even though testing was comprehensive, the specific test cases where this could have been detected were not included.
Lastly, during audits, auditors did not thoroughly review this interaction between StakingV1 and StakingV2 because it was presumed that StakingV1 functionality was out of the scope of this upgrade. These process failures forwarded this bug into production. Outcomes Kwenta CCs have decided the best course of action is to reverse the migration process until StakingV2 issues have been resolved and the code re-audited. This is the best decision for the security of the protocol. The current plan is to remove all StakingV1-related code from the StakingV2 contracts. A migration contract will also help stakers port their V1 escrow to V2 escrow (therefore, it can be staked).
- Upgrade the StakingRewardsV2 contracts to unpause the unstake and unstakeEscrow functions
- Provide a recovery function to collect the newly minted, not yet distributed rewards.
- Upgrade the RewardEscrowV2 function to fix the earlyVestFee at 0, so users can vest any rewards collected in the V2 contracts without penalty
- Collect the newly minted supply from the StakingRewardsV2 contract
- Point the SupplySchedule back to StakingRewardsV1
- Launched a simple UI to help stakers unstake from V2 Possible via governance: Decrease the treasuryDiversion to route back the missed rewards to V1 stakers
A custom migration contract will be built that allows migration from V1 to V2 for escrow entries. Then the Staking V2 contracts will no longer check V1 balances; instead, all rewards will go to V2 stakers, but everyone will be able to migrate.
If you haven't already, join the Kwenta community on Discord.
To be the first to learn about new updates to Kwenta, follow us on Twitter.
To trade synthetic assets and futures, visit Kwenta.
At 2 AM UTC Friday, July 14th, 2023, a potential vulnerability was discovered by Kwenta smart contract engineers in the set of StakingV2 contracts that put newly minted inflationary rewards at risk. This was later validated by a proof of concept (PoC) test case. Relevant parties were alerted and gathered. Swift action was taken by the Kwenta protocolDAO (pDAO) to pause the StakingV2 contracts to secure staker funds.
Analysis continued into the weekend, with auditors engaged, to fully understand the issue and prepare a potential rollback of the migration.
A decision to reverse the migration was made on Monday.
Thankfully, the launch of StakingV2 had only occurred a few hours prior, and the vulnerability was discovered internally before funds were at risk. As of this time, all funds are safe, and a reverse migration is taking place.
The vulnerability stems from the fact that StakingV1, when stake and unstake actions occur, does not alert the StakingV2 contract of these state changes.
The Staking contract works when an action (like stake/unstake) is performed, and the amount of reward tokens owed to you in the time (based on your stake) that has passed is recorded. Because StakingV1 actions do not alert StakingV2 properly, it's possible to lose all or extract more rewards than is deserved.
The migration process was halted because the bug could be encountered during the migration flow from StakingV1 to StakingV2. If a V1 staker begins accruing V2 rewards and then attempts to unstake from StakingV1 in order to migrate to StakingV2, all V2 accrued rewards (or rewards pertaining to the now unstaked "liquid" stake) are lost because the earned amount is not properly recorded on the V2 contract.
function test_Actual() public {
fundAccountAndStakeV1(user1, 10 ether);
vm.warp(block.timestamp + 1 weeks);
vm.prank(user1);
stakingRewardsV1.unstake(10 ether);
uint reward = stakingRewardsV2.rewards(user1);
assert(reward > 0);
}
Eventually, this issue revealed deeper issues within the StakingV2 contracts. For example, it is possible to manipulate the V1 stake function to generate more rewards than are deserved.
By increasing your V1 stake (potentially with a flashloan) before claiming rewards, your earned rewards can be manipulated because your previous staked amount isnβt properly accounted for on the V2 contract.
Therefore, when you go to claim your rewards, it will be based on your new staked balance * the time since the original stake event.
function test_Flash_Attack() public {
uint256 totalNewRewards = 100_000 ether;
fundAccountAndStakeV2(user1, 100 ether);
fundAccountAndStakeV2(user2, 100 ether);
addNewRewardsToStakingRewardsV2(totalNewRewards);
vm.warp(block.timestamp + 4 weeks);
// flash attack
uint256 fundsBorrwedViaFlashLoan = 100_000 ether;
fundAccountAndStakeV1(user3, fundsBorrwedViaFlashLoan);
vm.prank(user3);
stakingRewardsV2.getReward();
uint256 escrowedBalance = rewardEscrowV2.escrowedBalanceOf(user3);
// users claimed at least 99.8% of all the rewards
assertCloseTo(escrowedBalance, totalNewRewards, 200 ether);
// then user would pay back the flash loan
}
Kwenta has multiple security processes to prevent issues like these; however, there is always a non-zero chance of an incident. All new code undergoes thorough testing utilizing Foundry's testing suite. Kwenta Engineering makes use of unit, integration, fork tests, and extended testing tools like fuzz and invariant tests.
We enforce 80+% code coverage. The code is then reviewed internally by the Core Contributors (CCs) and then external auditors, such as our partners Macro and Omniscia, for vulnerabilities and potential edge cases. Lastly, post-launch, we set up monitoring tools (Tenderly alerts for invariants) and bug bounty programs to limit any potential vulnerabilities that may crop up in production.
In this case, the logic behind the Staking contracts during development was a misunderstanding. It was not enough to pull StakingV1 balances into the StakingV2 contract only when V2 balances were changed. Unfortunately, there were a few internal process failures that could have mitigated this issue.
StakingV2 is a large, intricate system with many new technical features and expected legacy support. Most of these changes were delivered as a monolithic pull request on Github, making it hard for the internal team to scrutinize every feature and modification. Secondly, even though testing was comprehensive, the specific test cases where this could have been detected were not included.
Lastly, during audits, auditors did not thoroughly review this interaction between StakingV1 and StakingV2 because it was presumed that StakingV1 functionality was out of the scope of this upgrade. These process failures forwarded this bug into production. Outcomes Kwenta CCs have decided the best course of action is to reverse the migration process until StakingV2 issues have been resolved and the code re-audited. This is the best decision for the security of the protocol. The current plan is to remove all StakingV1-related code from the StakingV2 contracts. A migration contract will also help stakers port their V1 escrow to V2 escrow (therefore, it can be staked).
- Upgrade the StakingRewardsV2 contracts to unpause the unstake and unstakeEscrow functions
- Provide a recovery function to collect the newly minted, not yet distributed rewards.
- Upgrade the RewardEscrowV2 function to fix the earlyVestFee at 0, so users can vest any rewards collected in the V2 contracts without penalty
- Collect the newly minted supply from the StakingRewardsV2 contract
- Point the SupplySchedule back to StakingRewardsV1
- Launched a simple UI to help stakers unstake from V2 Possible via governance: Decrease the treasuryDiversion to route back the missed rewards to V1 stakers
A custom migration contract will be built that allows migration from V1 to V2 for escrow entries. Then the Staking V2 contracts will no longer check V1 balances; instead, all rewards will go to V2 stakers, but everyone will be able to migrate.
If you haven't already, join the Kwenta community on Discord.
To be the first to learn about new updates to Kwenta, follow us on Twitter.
To trade synthetic assets and futures, visit Kwenta.
No activity yet