Skip to content

Commit

Permalink
Sonic Staking (#2335)
Browse files Browse the repository at this point in the history
* bumped the deploy script number

* Cap the validators a Native Staking Strategy can hold (#2087)

* Added max validators check to Native Staking Strategy

* don't format Defender Action code in dist folder

* Deployed latest NativeStakingSSVStrategy contract to Holesky

* Fix deployment file

* updated deploy number for OETH withdrawal queue

* Fixed unit tests

* Remove stETH from Vault in OETH Withdrawal Queue deployment is not already done
Skip Lido Withdrawal Strategy tests

* Skipping OETH Vault collateral swaps

* Skipping OETH whale redeem in fork tests
Added OETH whale request withdrawal to fork tests

* Fixed spelling in comments of VaultStorage

* Fail CI if any mainnet fork tests fail

* Continue with fork tests if any fail but still fail the CI job

* increment deploy script number

* restore Github Actions config

* Updated OETHVaultCore comments

* Upgraded OETH Vault on Holesky to include the withdrawal queue

* Added Vault requestWithdrawal andclaimWithdrawal Hardhat tasks
Added Dripper collect and setDripDuration Hardhat tasks

* OETHVaultCore Natspec updates
OETHVaultCore params with an underscore

* Add 30 minute time delay between request and claim from the OETH Withdrawal Queue. (#2127)

* feat: add delay between request and claim.

* test: update test with delay.

* fix: move `CLAIM_DELAY` from `VaultStorage.sol` to `OETHVaultCore.sol`.

* style: require error message start with capital letter.

---------

Co-authored-by: Nicholas Addison <[email protected]>

* fix: test expectRevert with new error message

* Fixed unit tests

* Remove stETH and rETH asset from OETH Vault
Remove legacy strategies from the Vault

* Skip legacy strategy tests

* Skiped legacy Oracle prices

* Skipped Aura price tests

* Remove rETH as an asset from the Vault

* Added call to cacheWETHAssetIndex after stETH is removed from  the Vault

* Updated vault storage diagrams

* Added second native staking strategy as the default for WETH

* Add solvency check. (#2131)

* feat: add solvency check.

* test: add test for solvency check.

* docs: add comments

* test: add more assertions.

* style: run prettier

* test: redeem with fees.

* test: increase coverage.

* test: increase coverage again.

* fix: failing test.

* Fixed claim Natspec now the delay is in place

* Changed console debug in assertUpgradeIsSafe to use logger

* Updated Natspec

* Assert totalValue in withdrawal queue unit tests

* Fixed prettier

* Asset vault checkBalance of WETH to OETH Vault unit tests

* _checkBalance and _totalValue on OETH Vault to protect against insolvency with most users requesting a withdrawal

* Override _totalValueInVault in OETH Vault

* Removed super._totalValue call

* Fix AMO fork tests

* Generated latest OETH Vault diagrams

* Don't account for WETH reserved for withdrawal during allocation (#2138)

* Override allocate method

* Add test

* WIP more unit tests

* Added more unit tests

* Added more withdrawal unit tests

* Fix skipped test

* Add extra test to OETH ARM. (#2139)

* test: add extra fork test for claiming withdraw.

* fix: div by zero on `_postRedeem()`.

* test: add test when vault is insolvent.

* test: when enough WETH in vault to cover exactly withdraw.

* test: when more than enough WETH in vault to cover withdraw.

* fix: reduce delay period between request and claim to 10min. (#2140)

* Refactor OETH Vault's `_allocate()` (#2141)

* Refactor of OETH Vault's _allocate

* Updated allocate test

* Add extra test for OETH Withdraw Queue  (#2142)

* test: add tests for `_allocate()`.

* Override allocate on OETH Vault so _addWithdrawalQueueLiquidity is not called twice on large mints (#2144)

OEH Vault _allocate exits early if no default WETH strategy

* Skip waiting for confirmation on Tenderly testnets

* Fix unit tests

* Add snapVault hardhat task

* Updated insolvency unit tests

* Added more insolvency unit tests

* Fix _totalValue so it handles when vault value is less than the outstanding withdrawal requests

* Added SafeCast to unit128

* Reject redeems and withdrawals if no available assets due to insolvency

* Redeem to no longer try and get liquidity from the default strategy if not enough available WETH in the vault

* Simplify _wethAvailable

* refactor of _claimWithdrawal

* Generated latest OETHVaultCore diagram

* Fix Slither

* Updated the other _wethAvailable function

* Set Vault buffer to 0.2%

* Swapped order in deploy script

* Simplify _totalValue logic

* Moved the burn of OETH lower in the request withdrawal

* Added reentrant protection to addWithdrawalQueueLiquidity

* Refactor _addWithdrawalQueueLiquidity
Removed nonReentrant on addWithdrawalQueueLiquidity for now

* Added vault buffer to snapVault Hardhat task

* M-01 _checkBalance Returns an Incorrect Value During Insolvency (#2166)

* Fix checkBalance bug in new OETHVaultCore (#2162)

* Added unit test for checkBalance when balance is less than the outstanding requests

* Fix _checkBalance so it returns 0 when the amount of WETH in the vault and strategies is less than the outstanding withdrawal requests

* Moved asset check to top of _checkBalance

* simplified _totalValue by calling _checkBalance (#2163)

* Fix vault storage slots (#2167)

* L-03 Missing Docstrings (#2169)

* Added Natspec to VaultStorage

* Added Natspec to VaultCore

* Fixed Natspec on requestWithdrawal (#2170)

* Changed _requestIds param in claimWithdrawals be of type calldata (#2171)

* Remove unnecessary address cast (#2172)

* Updated Natpsec of _checkBalance and _checkBalance (#2173)

* made constant CLAIM_DELAY public (#2174)

* Removed unused MAX_UINT constant (#2175)

* N-08 Variables Are Initialized to Their Default Values (#2176)

* Removed unused MAX_UINT constant

* Removed variables being initialized to their default values

* Generated latest Vault contract diagrams

* initial commit

* WIP Sonic Vault

* Changed Sonic Vault to use OETH Base Vault

* WIP sonic

* WIP sonic

* WIP sonic

* Got unit tests working

* Added sonic to node script

* WIP Sonic deploy script

* Added sonic to storageSlots

* Fix getHardhatNetworkProperties

* Added sonic deployment files

* Added WETH address on Sonic

* Fix Sonic deployment

* Upgraded Hardhat

* More Sonic deployment changes

* More Sonic fixes

* Sonic VaultAdmin override supportAsset as it doesn't have a price provider

* Solidity prettier

* Skipping reborn attack tests now self-destruct has been removed

* fix reborn tests

* re-enable fixed reborn tests

* Added SPC

* fix reborn tests

* Fix Solidity compile

* WIP Sonic Staking Strategy

* Add supported validators to Sonic Staking Strategy

* Added Sonic Staking Strategy to deploy script

* checkBalance now gets stake and pending rewards

* add basic fork tests for Sonic staking

* add correct validator ids

* Added Defender Relayer for Sonic

* Fixed Sonic unit tests
Prettier and linter

* More admin unit tests

* More unit tests

* Update dependencies

* bumped solidity-coverage version

* Added Sonic tests to CI

* Fix deprecation notices
Renamed actions

* Formatting of fork-test.sh script

* Slither fixes

* Removed unit tests to get gas numbers from CI

* Removed redeem from OSonicVault

* Removed unused code from SonicValidatorDelegator

* clean up fork test structure

* improve fork test checks

* add basic withdrawal tests

* prettier

* Fix OSonic unit test deploy after merge with yield delegation

* Added Fixed Rate Dripper for Sonic

* Fixed base unit tests after
Fix upgrade script of OETHBase

* Added Sonic Zapper

* Added Sonic contract dependency diagram

* add withdrawal fork tests

* add restaking test

* add withdrawal timestamp to the withdrawal struct

* Updated Sonic token metadata

* prettier

* Update Natspec
Added governor transfer unit tests

* Added VaultValueChecker to Sonic deploy script

* Added phase 2 contracts to Sonic contract dependencies

* Generated Sonic contract diagrams
Updated existing OToken diagrams after Yield Delegation

* Added Sonic fork tests for Zapper

* Reduced depositedWSAccountedFor when delegating or withdrawing from the Sonic Staking Strategy

* Generated latest SonicStakingStrategy

* Added Sonic Vault config to deploy script

* Added TODO in Sonic addresses

* Added Sonic Vault fork tests
Added missing Vault config to Sonic deploy script
Sonic Staking Strategy governor fixed in deploy script

* remove the depositedWSAccountedFor

* automatically delegate on deposit transaction & add strategist allowance to undelegate

* add donation attack comment and pick up any S tokens in the withdrawAll

* Prettier

* Cleaned up imports
Updated __gap after adding defaultValidatorId

* Fix Slither

* Updated Natspec

* Removed Deposit event from restakeRewards

* Fix Natspec

* Fix fork tests after removing Deposit event from restakeRewards
More Natspec updated

* Added deposit and withdraw fork tests for sonic staking strategy

* Added more Sonic fork tests

* Generated latest Sonic Strategy diagrams

* update the solc version to re-enable harhdat tracer

* Added Sonic Admin and Guardian wallets

* Added logger to Sonic staking fork tests

* update the compiler version to 0.8.28

* Prettier

(cherry picked from commit fe45bce)

* Added Timelock to Sonic deploy script

(cherry picked from commit 2c3e2e4)

* deployOnSonic now handles Timelock governance
Split Sonic deploy up into vault/tokens and sonic staking strategy

(cherry picked from commit d57fd0c)

* cleaner max int

* remove unused variable

* simplify casting

* remove secondary 0 amount check

* gas optimisation

* fix incorrect type

* Sonic Deploy 001 - Token and Vault  (#2352)

* fix incorrect type

* update hardhat-verify to support sonic chain verifications

* add descriptors of sonic 001 deploy

* remove trustee address and feeBps setting

* Prettier

---------

Co-authored-by: Domen Grabec <[email protected]>

* add oracle router deployment (#2353)

* add oracle router deployment

* Renamed Router to be consistent with other Sonic contracts

* Added oracle router to Sonic contract diagram

---------

Co-authored-by: Nicholas Addison <[email protected]>

* Revert change to MAX_INT in VaultCore

* Changed withConfirmation it ignore confirmations to Sonic and Base Tenderly Testnets

* change max int notation

* Correct chainId when generating Gnosis file

(cherry picked from commit 27b4e82)

* create a separate contract for OSonicOracleRouter

* Hardhat tasks working with Sonic (#2357)

* Made depositWETH work with Sonic

* HH tasks allocate, capital, rebase, mint, requestWithdrawal, claimWithdrawal and  and snapVault working with Sonic

* correct comment

* correct comment

* allow restaking only of the supported validators

* add SonicOracleRouter deployment files (#2355)

* add the ability to claim rewards without restaking them

* emit Withdrawal event when funds withdrawn from the strategy

* simplify ACL

* Store contract state before executing external calls

* automatically undelegate when unsupporting a validator

* remove comment

* remove slither disables

* add test for confirming rewards being restaked

* emit withdrawal event when collecting rewards

* Sonic 003 deploy script changed to config vault and upgrade Wrapped OS token

* remove the non required is validator supported check

* add test for depositAll

* add some missing tests

* add test for not receiving sonic

* add comment

* add trustee address to the deploy script

* correct local variable names

* Sonic Deploy 003 - Sonic Staking Strategy (#2359)

* Added setAssetDefaultStrategy to Sonic deploy 003 script

* Added setDefaultValidator Hardhat task

* Fixed Sonic fork tests now mints are auto allocating to the Sonic Staking Strategy

* Sonic deploy 003 contracts

---------

Co-authored-by: Shahul Hameed <[email protected]>
Co-authored-by: Clément <[email protected]>
Co-authored-by: clement-ux <[email protected]>
Co-authored-by: Domen Grabec <[email protected]>
  • Loading branch information
5 people authored Jan 22, 2025
1 parent ebdc81c commit 097f3f3
Show file tree
Hide file tree
Showing 96 changed files with 20,207 additions and 253 deletions.
12 changes: 12 additions & 0 deletions contracts/contracts/interfaces/sonic/INodeDriver.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

interface INodeDriver {
/// Seal epoch. Called BEFORE epoch sealing made by the client itself.
function sealEpoch(
uint256[] calldata offlineTimes,
uint256[] calldata offlineBlocks,
uint256[] calldata uptimes,
uint256[] calldata originatedTxsFee
) external;
}
282 changes: 282 additions & 0 deletions contracts/contracts/interfaces/sonic/ISFC.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,282 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

/**
* @title Special Fee Contract for Sonic network
* @notice The SFC maintains a list of validators and delegators and distributes rewards to them.
* @custom:security-contact [email protected]
*/
interface ISFC {
event CreatedValidator(
uint256 indexed validatorID,
address indexed auth,
uint256 createdEpoch,
uint256 createdTime
);
event Delegated(
address indexed delegator,
uint256 indexed validatorID,
uint256 amount
);
event Undelegated(
address indexed delegator,
uint256 indexed validatorID,
uint256 indexed wrID,
uint256 amount
);
event Withdrawn(
address indexed delegator,
uint256 indexed validatorID,
uint256 indexed wrID,
uint256 amount,
uint256 penalty
);
event ClaimedRewards(
address indexed delegator,
uint256 indexed validatorID,
uint256 rewards
);
event RestakedRewards(
address indexed delegator,
uint256 indexed validatorID,
uint256 rewards
);
event BurntFTM(uint256 amount);
event UpdatedSlashingRefundRatio(
uint256 indexed validatorID,
uint256 refundRatio
);
event RefundedSlashedLegacyDelegation(
address indexed delegator,
uint256 indexed validatorID,
uint256 amount
);

event DeactivatedValidator(
uint256 indexed validatorID,
uint256 deactivatedEpoch,
uint256 deactivatedTime
);
event ChangedValidatorStatus(uint256 indexed validatorID, uint256 status);
event AnnouncedRedirection(address indexed from, address indexed to);

function currentSealedEpoch() external view returns (uint256);

function getEpochSnapshot(uint256 epoch)
external
view
returns (
uint256 endTime,
uint256 endBlock,
uint256 epochFee,
uint256 baseRewardPerSecond,
uint256 totalStake,
uint256 totalSupply
);

function getStake(address delegator, uint256 validatorID)
external
view
returns (uint256);

function getValidator(uint256 validatorID)
external
view
returns (
uint256 status,
uint256 receivedStake,
address auth,
uint256 createdEpoch,
uint256 createdTime,
uint256 deactivatedTime,
uint256 deactivatedEpoch
);

function getValidatorID(address auth) external view returns (uint256);

function getValidatorPubkey(uint256 validatorID)
external
view
returns (bytes memory);

function pubkeyAddressvalidatorID(address pubkeyAddress)
external
view
returns (uint256);

function getWithdrawalRequest(
address delegator,
uint256 validatorID,
uint256 wrID
)
external
view
returns (
uint256 epoch,
uint256 time,
uint256 amount
);

function isOwner() external view returns (bool);

function lastValidatorID() external view returns (uint256);

function minGasPrice() external view returns (uint256);

function owner() external view returns (address);

function renounceOwnership() external;

function slashingRefundRatio(uint256 validatorID)
external
view
returns (uint256);

function stashedRewardsUntilEpoch(address delegator, uint256 validatorID)
external
view
returns (uint256);

function totalActiveStake() external view returns (uint256);

function totalStake() external view returns (uint256);

function totalSupply() external view returns (uint256);

function transferOwnership(address newOwner) external;

function treasuryAddress() external view returns (address);

function version() external pure returns (bytes3);

function currentEpoch() external view returns (uint256);

function updateConstsAddress(address v) external;

function constsAddress() external view returns (address);

function getEpochValidatorIDs(uint256 epoch)
external
view
returns (uint256[] memory);

function getEpochReceivedStake(uint256 epoch, uint256 validatorID)
external
view
returns (uint256);

function getEpochAccumulatedRewardPerToken(
uint256 epoch,
uint256 validatorID
) external view returns (uint256);

function getEpochAccumulatedUptime(uint256 epoch, uint256 validatorID)
external
view
returns (uint256);

function getEpochAverageUptime(uint256 epoch, uint256 validatorID)
external
view
returns (uint32);

function getEpochAccumulatedOriginatedTxsFee(
uint256 epoch,
uint256 validatorID
) external view returns (uint256);

function getEpochOfflineTime(uint256 epoch, uint256 validatorID)
external
view
returns (uint256);

function getEpochOfflineBlocks(uint256 epoch, uint256 validatorID)
external
view
returns (uint256);

function getEpochEndBlock(uint256 epoch) external view returns (uint256);

function rewardsStash(address delegator, uint256 validatorID)
external
view
returns (uint256);

function createValidator(bytes calldata pubkey) external payable;

function getSelfStake(uint256 validatorID) external view returns (uint256);

function delegate(uint256 validatorID) external payable;

function undelegate(
uint256 validatorID,
uint256 wrID,
uint256 amount
) external;

function isSlashed(uint256 validatorID) external view returns (bool);

function withdraw(uint256 validatorID, uint256 wrID) external;

function deactivateValidator(uint256 validatorID, uint256 status) external;

function pendingRewards(address delegator, uint256 validatorID)
external
view
returns (uint256);

function stashRewards(address delegator, uint256 validatorID) external;

function claimRewards(uint256 validatorID) external;

function restakeRewards(uint256 validatorID) external;

function updateSlashingRefundRatio(uint256 validatorID, uint256 refundRatio)
external;

function updateTreasuryAddress(address v) external;

function burnFTM(uint256 amount) external;

function sealEpoch(
uint256[] calldata offlineTime,
uint256[] calldata offlineBlocks,
uint256[] calldata uptimes,
uint256[] calldata originatedTxsFee
) external;

function sealEpochValidators(uint256[] calldata nextValidatorIDs) external;

function initialize(
uint256 sealedEpoch,
uint256 _totalSupply,
address nodeDriver,
address consts,
address _owner
) external;

function setGenesisValidator(
address auth,
uint256 validatorID,
bytes calldata pubkey,
uint256 createdTime
) external;

function setGenesisDelegation(
address delegator,
uint256 validatorID,
uint256 stake
) external;

function updateStakeSubscriberAddress(address v) external;

function stakeSubscriberAddress() external view returns (address);

function setRedirectionAuthorizer(address v) external;

function announceRedirection(address to) external;

function initiateRedirection(address from, address to) external;

function redirect(address to) external;
}
33 changes: 33 additions & 0 deletions contracts/contracts/interfaces/sonic/IWrappedSonic.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface IWrappedSonic {
function allowance(address owner, address spender)
external
view
returns (uint256);

function approve(address spender, uint256 value) external returns (bool);

function balanceOf(address account) external view returns (uint256);

function decimals() external view returns (uint8);

function deposit() external payable;

function depositFor(address account) external payable returns (bool);

function totalSupply() external view returns (uint256);

function transfer(address to, uint256 value) external returns (bool);

function transferFrom(
address from,
address to,
uint256 value
) external returns (bool);

function withdraw(uint256 value) external;

function withdrawTo(address account, uint256 value) external returns (bool);
}
69 changes: 69 additions & 0 deletions contracts/contracts/mocks/MockSFC.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "./MintableERC20.sol";

contract MockSFC {
error ZeroAmount();
error TransferFailed();

// Mapping of delegator address to validator ID to amount delegated
mapping(address => mapping(uint256 => uint256)) public delegations;
// Mapping of delegator address to validator ID to withdrawal request ID to amount
mapping(address => mapping(uint256 => mapping(uint256 => uint256)))
public withdraws;

function getStake(address delegator, uint256 validatorID)
external
view
returns (uint256)
{
return delegations[delegator][validatorID];
}

function delegate(uint256 validatorID) external payable {
if (msg.value == 0) {
revert ZeroAmount();
}
delegations[msg.sender][validatorID] += msg.value;
}

function undelegate(
uint256 validatorID,
uint256 wrID,
uint256 amount
) external {
require(
delegations[msg.sender][validatorID] >= amount,
"insufficient stake"
);
require(
withdraws[msg.sender][validatorID][wrID] == 0,
"withdrawal request already exists"
);

delegations[msg.sender][validatorID] -= amount;
withdraws[msg.sender][validatorID][wrID] = amount;
}

function withdraw(uint256 validatorID, uint256 wrID) external {
require(withdraws[msg.sender][validatorID][wrID] > 0, "no withdrawal");

(bool sent, ) = msg.sender.call{
value: withdraws[msg.sender][validatorID][wrID]
}("");
if (!sent) {
revert TransferFailed();
}
}

function pendingRewards(address delegator, uint256 validatorID)
external
view
returns (uint256)
{}

function claimRewards(uint256 validatorID) external {}

function restakeRewards(uint256 validatorID) external {}
}
Loading

0 comments on commit 097f3f3

Please sign in to comment.