-
Notifications
You must be signed in to change notification settings - Fork 8
Upgradeable staker (DO NOT MERGE) #154
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 13 commits
6ec6f67
327efc8
f172dee
20cf975
579d557
259848a
c5787f6
e940b6a
e7488ac
0ee5b71
a462379
366e7f3
dd11571
2932a1b
2fe8124
97687dc
1596bcc
126860b
768dc70
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| { | ||
| "lib/openzeppelin-contracts": { | ||
| "rev": "dbb6104ce834628e473d2173bbc9d47f81a9eec3" | ||
| }, | ||
| "lib/openzeppelin-contracts-upgradeable": { | ||
| "tag": { | ||
| "name": "v5.4.0", | ||
| "rev": "e725abddf1e01cf05ace496e950fc8e243cc7cab" | ||
| } | ||
| }, | ||
| "lib/forge-std": { | ||
| "rev": "1714bee72e286e73f76e320d110e0eaf5c4e649d" | ||
| } | ||
| } |
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,7 @@ | ||
| // SPDX-License-Identifier: AGPL-3.0-only | ||
| pragma solidity ^0.8.23; | ||
|
|
||
| import {Staker} from "../Staker.sol"; | ||
| import {StakerUpgradeable} from "../StakerUpgradeable.sol"; | ||
|
|
||
| /// @title StakerCapDeposits | ||
| /// @author [ScopeLift](https://scopelift.co) | ||
|
|
@@ -11,21 +11,47 @@ import {Staker} from "../Staker.sol"; | |
| /// The contract allows the admin to configure a total stake cap that applies across all deposits. | ||
| /// Any attempt to stake tokens that would cause the total staked amount to exceed this cap will | ||
| /// revert. | ||
| abstract contract StakerCapDeposits is Staker { | ||
| abstract contract StakerCapDepositsUpgradeable is StakerUpgradeable { | ||
| /// @notice Emitted when the total stake cap is changed. | ||
| /// @param oldTotalStakeCap The previous maximum total stake allowed. | ||
| /// @param newTotalStakeCap The new maximum total stake allowed. | ||
| event TotalStakeCapSet(uint256 oldTotalStakeCap, uint256 newTotalStakeCap); | ||
|
|
||
| /// @notice Thrown when a staking operation would cause the total staked amount to exceed the | ||
| /// cap. | ||
| error StakerCapDeposits__CapExceeded(); | ||
| error StakerCapDepositsUpgradeable__CapExceeded(); | ||
|
|
||
| /// @notice The maximum total amount of tokens that can be staked across all deposits. | ||
| uint256 public totalStakeCap; | ||
| struct StakerCapDepositsStorage { | ||
| /// @notice The maximum total amount of tokens that can be staked across all deposits. | ||
| uint256 _totalStakeCap; | ||
| } | ||
|
|
||
| // keccak256(abi.encode(uint256(keccak256("storage.scopelift.StakerCapDeposits")) - 1)) | ||
| // &~bytes32(uint256(0xff)) | ||
| bytes32 private constant STAKER_CAP_DEPOSITS_STORAGE_LOCATION = | ||
| 0x965a89691c17af92914eadf0e487b628b4de164741f52e43f2d8c224cfe56100; | ||
|
|
||
| function _getStakerCapDepositsStorage() private pure returns (StakerCapDepositsStorage storage $) { | ||
| assembly { | ||
| $.slot := STAKER_CAP_DEPOSITS_STORAGE_LOCATION | ||
| } | ||
| } | ||
|
|
||
| /// @notice Initializes the the contract. | ||
alexkeating marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| /// @param _initialTotalStakeCap The initial maximum total stake allowed. | ||
| constructor(uint256 _initialTotalStakeCap) { | ||
| function __StakerCapDepositsUpgradeable_init(uint256 _initialTotalStakeCap) | ||
| internal | ||
| onlyInitializing | ||
| { | ||
| __StakerCapDepositsUpgradeable_init_unchained(_initialTotalStakeCap); | ||
| } | ||
|
|
||
| /// @notice Initializes the the contract. | ||
alexkeating marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| /// @param _initialTotalStakeCap The initial maximum total stake allowed. | ||
| function __StakerCapDepositsUpgradeable_init_unchained(uint256 _initialTotalStakeCap) | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Kept these to match convention, but they seem to only be used as a passthrough |
||
| internal | ||
| onlyInitializing | ||
| { | ||
| _setTotalStakeCap(_initialTotalStakeCap); | ||
| } | ||
|
|
||
|
|
@@ -37,34 +63,41 @@ abstract contract StakerCapDeposits is Staker { | |
| _setTotalStakeCap(_newTotalStakeCap); | ||
| } | ||
|
|
||
| /// @notice The maximum total amount of tokens that can be staked across all deposits. | ||
alexkeating marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| function totalStakeCap() public view returns (uint256) { | ||
| StakerCapDepositsStorage storage $ = _getStakerCapDepositsStorage(); | ||
| return $._totalStakeCap; | ||
| } | ||
|
|
||
| /// @notice Internal helper method which sets a new total stake cap. | ||
| /// @param _newTotalStakeCap The new maximum total stake allowed. | ||
| function _setTotalStakeCap(uint256 _newTotalStakeCap) internal { | ||
| emit TotalStakeCapSet(totalStakeCap, _newTotalStakeCap); | ||
| totalStakeCap = _newTotalStakeCap; | ||
| StakerCapDepositsStorage storage $ = _getStakerCapDepositsStorage(); | ||
| emit TotalStakeCapSet($._totalStakeCap, _newTotalStakeCap); | ||
| $._totalStakeCap = _newTotalStakeCap; | ||
| } | ||
|
|
||
| /// @inheritdoc Staker | ||
| /// @inheritdoc StakerUpgradeable | ||
| /// @dev Checks if the stake would exceed the total stake cap before proceeding. | ||
| function _stake(address _depositor, uint256 _amount, address _delegatee, address _claimer) | ||
| internal | ||
| virtual | ||
| override(Staker) | ||
| override(StakerUpgradeable) | ||
| returns (DepositIdentifier _depositId) | ||
| { | ||
| _revertIfCapExceeded(_amount); | ||
| return Staker._stake(_depositor, _amount, _delegatee, _claimer); | ||
| return StakerUpgradeable._stake(_depositor, _amount, _delegatee, _claimer); | ||
| } | ||
|
|
||
| /// @inheritdoc Staker | ||
| /// @inheritdoc StakerUpgradeable | ||
| /// @dev Checks if the additional stake would exceed the total stake cap before proceeding. | ||
| function _stakeMore(Deposit storage deposit, DepositIdentifier _depositId, uint256 _amount) | ||
| internal | ||
| virtual | ||
| override(Staker) | ||
| override(StakerUpgradeable) | ||
| { | ||
| _revertIfCapExceeded(_amount); | ||
| Staker._stakeMore(deposit, _depositId, _amount); | ||
| StakerUpgradeable._stakeMore(deposit, _depositId, _amount); | ||
| } | ||
|
|
||
| /// @notice Internal helper method which reverts if adding a given stake amount would exceed the | ||
|
|
@@ -73,6 +106,9 @@ abstract contract StakerCapDeposits is Staker { | |
| /// @dev Reverts with StakerCapDeposits__CapExceeded if the amount would cause total stake to | ||
| /// exceed the cap. | ||
| function _revertIfCapExceeded(uint256 _amount) internal view virtual { | ||
| if ((totalStaked + _amount) > totalStakeCap) revert StakerCapDeposits__CapExceeded(); | ||
| StakerCapDepositsStorage storage $ = _getStakerCapDepositsStorage(); | ||
| if ((totalStaked() + _amount) > $._totalStakeCap) { | ||
| revert StakerCapDepositsUpgradeable__CapExceeded(); | ||
| } | ||
| } | ||
| } | ||
This file was deleted.
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,93 @@ | ||||||
| // SPDX-License-Identifier: AGPL-3.0-only | ||||||
| pragma solidity ^0.8.23; | ||||||
|
|
||||||
| import {DelegationSurrogate} from "../DelegationSurrogate.sol"; | ||||||
| import {DelegationSurrogateVotes} from "../DelegationSurrogateVotes.sol"; | ||||||
| import {StakerUpgradeable} from "../StakerUpgradeable.sol"; | ||||||
| import {IERC20Delegates} from "../interfaces/IERC20Delegates.sol"; | ||||||
|
|
||||||
| /// @title StakerDelegateSurrogateVotes | ||||||
| /// @author [ScopeLift](https://scopelift.co) | ||||||
| /// @notice This contract extension adds delegation surrogates to the Staker base | ||||||
| /// contract, allowing staked tokens to be delegated to a specific delegate. | ||||||
| abstract contract StakerDelegateSurrogateVotesUpgradeable is StakerUpgradeable { | ||||||
| /// @notice Emitted when a surrogate contract is deployed. | ||||||
| event SurrogateDeployed(address indexed delegatee, address indexed surrogate); | ||||||
|
|
||||||
| /// @notice Thrown if an inheritor misconfigures the staking token on deployment. | ||||||
| error StakerDelegateSurrogateVotesUpgradeable__UnauthorizedToken(); | ||||||
|
|
||||||
| struct StakerDelegateSurrogateVotesStorage { | ||||||
| /// @notice Maps the account of each governance delegate with the surrogate contract which holds | ||||||
| /// the staked tokens from deposits which assign voting weight to said delegate. | ||||||
| mapping(address delegatee => DelegationSurrogate surrogate) _storedSurrogates; | ||||||
| } | ||||||
|
|
||||||
| // keccak256(abi.encode(uint256(keccak256("storage.scopelift.StakerDelegateSurrogateVotes")) - 1)) | ||||||
| // &~bytes32(uint256(0xff)) | ||||||
| bytes32 private constant STAKER_DELEGATE_SURROGATE_STORAGE_LOCATION = | ||||||
| 0x010103b2a019a28f51fa63a98fe162dac866120b721518e29f318125463ff100; | ||||||
|
|
||||||
| function _getStakerDelegateSurrogateStorage() | ||||||
| private | ||||||
| pure | ||||||
| returns (StakerDelegateSurrogateVotesStorage storage $) | ||||||
| { | ||||||
| assembly { | ||||||
| $.slot := STAKER_DELEGATE_SURROGATE_STORAGE_LOCATION | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| /// @notice Initializes the the contract. | ||||||
alexkeating marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||
| /// @param _votingToken The token that is used for voting, which must be the same as the parent | ||||||
| /// Staker's STAKE_TOKEN. | ||||||
| function __StakerDelegateSurrogateVotesUpgradeable_init(IERC20Delegates _votingToken) | ||||||
| internal | ||||||
| onlyInitializing | ||||||
| { | ||||||
| __StakerDelegateSurrogateVotesUpgradeable_init_unchained(_votingToken); | ||||||
| } | ||||||
|
|
||||||
| /// @notice Initializes the the contract. | ||||||
|
||||||
| /// @notice Initializes the the contract. | |
| /// @notice Initializes the `StakerDelegateSurrogateVotesUpgradeable` contract. |
Uh oh!
There was an error while loading. Please reload this page.