Skip to content
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

WIP: Staking contract #453

Closed
wants to merge 501 commits into from
Closed
Show file tree
Hide file tree
Changes from 181 commits
Commits
Show all changes
501 commits
Select commit Hold shift + click to select a range
55ad8a7
Fixup
geoff-vball Sep 5, 2024
57256e9
require init end callable by owner
cam-schultz Sep 5, 2024
7616bb5
revamp delegation events
cam-schultz Sep 5, 2024
0a4ae92
fix e2e
cam-schultz Sep 5, 2024
68c9eaa
store starting validator weight
cam-schultz Sep 5, 2024
d63a131
Update contracts/staking/NativeTokenStakingManager.sol
cam-schultz Sep 5, 2024
24b9c61
Merge pull request #504 from ava-labs/delegation-poc
cam-schultz Sep 5, 2024
0834d6c
Merge branch 'staking-contract' into delegation-track-uptime
cam-schultz Sep 5, 2024
666f5d7
Merge pull request #520 from ava-labs/delegation-track-uptime
cam-schultz Sep 5, 2024
27e2063
Merge branch 'staking-contract' into delegation-id
cam-schultz Sep 5, 2024
e9db526
update mapping descriptions
cam-schultz Sep 5, 2024
aed4ed7
delegationID w/keccak; remove unnecessary check
cam-schultz Sep 5, 2024
de9845f
expand delegation comments
cam-schultz Sep 5, 2024
9930e65
Merge pull request #528 from ava-labs/delegation-id
cam-schultz Sep 5, 2024
b8f8f60
Update contracts/staking/interfaces/IPoSValidatorManager.sol
geoff-vball Sep 6, 2024
99a12a5
Update contracts/staking/interfaces/IPoSValidatorManager.sol
geoff-vball Sep 6, 2024
1e2489d
Merge pull request #530 from ava-labs/delegation-comments
geoff-vball Sep 6, 2024
01b6bab
Merge branch 'staking-contract' into churn-tracker
geoff-vball Sep 6, 2024
1c170e6
Fix test
geoff-vball Sep 6, 2024
fc99b2c
Add tests
geoff-vball Sep 6, 2024
c197215
Merge remote-tracking branch 'origin/staking-contract' into unlock-stake
feuGeneA Sep 6, 2024
fc51cdc
lint
geoff-vball Sep 6, 2024
03b96a1
rename to validatormanager
Sep 6, 2024
ba44522
lint
geoff-vball Sep 6, 2024
50ce587
validatormanager bindings
Sep 6, 2024
1ea4bfc
natspec style review comment
feuGeneA Sep 6, 2024
daa99b8
Move total weight tracking to ValidatorManager
geoff-vball Sep 6, 2024
b256857
Remove pendingEndValidationMessages
geoff-vball Sep 6, 2024
c5ccd92
Remove pendingRegisterDelegatorMessages
geoff-vball Sep 6, 2024
d54c724
Remove pendingEndDelegatorMessages
geoff-vball Sep 6, 2024
c785809
add unit tests
feuGeneA Sep 6, 2024
1ef6e2d
unlock starting weight, not weight w/ delegations
feuGeneA Sep 6, 2024
bae1c68
update abi bindings
feuGeneA Sep 6, 2024
6decd64
expect ERC20.transfer for stake unlock
feuGeneA Sep 6, 2024
fa3931d
expect native receive() for unlocked stake
feuGeneA Sep 6, 2024
9b9d856
Fix tests
geoff-vball Sep 6, 2024
eb140eb
Merge pull request #527 from ava-labs/unlock-stake
feuGeneA Sep 6, 2024
e87babf
Merge branch 'staking-contract' into unify-resend-methods
geoff-vball Sep 9, 2024
91fac1b
Merge branch 'staking-contract' into churn-tracker
geoff-vball Sep 9, 2024
a8af00f
parameterize values init
Sep 9, 2024
ea5a403
save validator requirements
Sep 9, 2024
612b626
unit tests passing
Sep 9, 2024
299d3a4
add initializer tests
Sep 9, 2024
0dd5b6c
invalid validator requirements
Sep 9, 2024
8be8b5e
unlock stake at delegation end
feuGeneA Sep 10, 2024
310fbca
Merge pull request #539 from ava-labs/unlock-stake-for-delegators
feuGeneA Sep 10, 2024
c6c290d
`IERC20Mintable`, not `IERC20`
feuGeneA Sep 6, 2024
318c277
issue ERC20 staking rewards (native rewards TBD)
feuGeneA Sep 6, 2024
1763ca2
Update contracts/staking/PoSValidatorManager.sol
geoff-vball Sep 10, 2024
cd497d7
Merge branch 'staking-contract' into churn-tracker
geoff-vball Sep 10, 2024
c6dd4b3
Remove churn tracker start time
geoff-vball Sep 10, 2024
f52c04a
Churn tracker to ValidatorManager
geoff-vball Sep 10, 2024
f45cce7
mint(addr,amount): respect _MAX_MINT
feuGeneA Sep 10, 2024
57a519e
incorporate uptime in rewards
feuGeneA Sep 11, 2024
538ea24
Fixup churn tracker
geoff-vball Sep 11, 2024
c4ec69c
Fix tests
geoff-vball Sep 11, 2024
1fc2700
Fix comment
geoff-vball Sep 11, 2024
4281078
Fixups
geoff-vball Sep 11, 2024
62c73d2
Merge branch 'staking-contract' into unify-resend-methods
geoff-vball Sep 11, 2024
06ef037
Add comment
geoff-vball Sep 11, 2024
f26ecbe
increment validator rewards, not overwrite them
feuGeneA Sep 11, 2024
f5d460a
rename back to staking and lint
Sep 11, 2024
794e29d
Merge remote-tracking branch 'origin/staking-contract' into min-stake…
Sep 11, 2024
35bb886
bindings
Sep 11, 2024
e336fc7
add cap to maximum stake multiplier
Sep 11, 2024
a34ab4f
allow 0 maximum stake multiplier
Sep 11, 2024
437d61e
update e2e tests
Sep 11, 2024
16e04fc
zero min staking duration
Sep 12, 2024
4b61e03
handle initial validator end
Sep 10, 2024
4a35b8c
initial validator draft
Sep 10, 2024
f502ea7
change in initialize
Sep 11, 2024
d3b8ccc
remove owner as part of validator struct
Sep 12, 2024
de7ab80
draft with initialValidatorSet, removing owner from ValidatorManager,…
Sep 12, 2024
006de7e
Merge pull request #536 from ava-labs/unify-resend-methods
geoff-vball Sep 12, 2024
0d815a0
fix checks for initial validator set
Sep 12, 2024
e367998
Merge branch 'staking-contract' into churn-tracker
geoff-vball Sep 12, 2024
2be8305
remove enumerable set use
Sep 12, 2024
e0ca117
fix up delegation fees and add unit tests
Sep 12, 2024
b86ec1a
change types for parameterized valuse
Sep 12, 2024
731c77f
Merge remote-tracking branch 'origin/staking-contract' into min-stake…
Sep 12, 2024
d704a40
add max for minimum delegation fee
Sep 12, 2024
eb844c5
add max check for min delegation fee
Sep 12, 2024
6c697c3
bindings
Sep 12, 2024
6b1670b
Merge branch 'min-stake-duration' into initial-validators-ending
Sep 12, 2024
9fa3ec2
fix merge
Sep 12, 2024
06e650e
pr fixes
Sep 13, 2024
b906016
e2e tests fixing
Sep 13, 2024
0fa897d
Review fixes
geoff-vball Sep 13, 2024
95b20fa
min stake duration not passing
Sep 13, 2024
1836583
Fix unit tests
geoff-vball Sep 13, 2024
ceff4ed
Fix e2e tests
geoff-vball Sep 13, 2024
2eb6d02
Add comment
geoff-vball Sep 13, 2024
6372e82
min stake duration fix
iansuvak Sep 13, 2024
4894609
add public getValidator function and fix e2e test
Sep 13, 2024
99976c1
Merge pull request #550 from ava-labs/min-stake-duration-block
Sep 13, 2024
72a6417
add utils and fix lint
Sep 13, 2024
65cf972
Fix e2e tests
geoff-vball Sep 13, 2024
bb8b32c
Merge pull request #544 from ava-labs/min-stake-duration
Sep 13, 2024
94cc0d8
Merge branch 'staking-contract' into churn-tracker
geoff-vball Sep 13, 2024
0542c82
Fix most unit tests
geoff-vball Sep 13, 2024
07dd6f2
Merge remote-tracking branch 'origin/staking-contract' into initial-v…
Sep 13, 2024
2c1a1b1
unit tests compile but need initial validator set
Sep 13, 2024
1dcb74c
bindings
Sep 13, 2024
b7f2677
bug fixes
Sep 13, 2024
ba9024c
Fix most unit tests
geoff-vball Sep 13, 2024
58d5803
Fix all unit tests
geoff-vball Sep 13, 2024
22a0a8c
Fix e2e tests
geoff-vball Sep 13, 2024
0c67133
Review fixes
geoff-vball Sep 13, 2024
d103844
Review fixes
geoff-vball Sep 13, 2024
91bef5d
Merge pull request #511 from ava-labs/churn-tracker
Sep 14, 2024
fd0aa94
Merge branch 'staking-contract' into staking-rewards
geoff-vball Sep 16, 2024
6ba67b6
Fixup
geoff-vball Sep 16, 2024
56304eb
Fix tests
geoff-vball Sep 16, 2024
08d95b8
Fix rewards calculator
geoff-vball Sep 16, 2024
6fbb9ad
WIP but not working at all yet
iansuvak Sep 16, 2024
f2c13d5
Fixups
geoff-vball Sep 16, 2024
267d92e
Fixups
geoff-vball Sep 16, 2024
dabde59
Fixups
geoff-vball Sep 16, 2024
d480b4c
Fixups
geoff-vball Sep 16, 2024
2ecf2bf
lint
geoff-vball Sep 16, 2024
e29827c
Native staking rewards
feuGeneA Sep 11, 2024
38be7d9
update initial validator set verification to take into account extra …
Sep 16, 2024
2806198
Update contracts/staking/ValidatorMessages.sol
Sep 16, 2024
05cb8d7
pack subnet conversion message
Sep 16, 2024
db1867d
gets through signing step but fails the subnetconversion hash check
iansuvak Sep 16, 2024
c382766
Merge remote-tracking branch 'origin/initial-validators-ending' into …
iansuvak Sep 16, 2024
dcadbf1
poa validator manager test passes
iansuvak Sep 16, 2024
9766b4e
replace manual encoding with BigEndian Put methods
iansuvak Sep 16, 2024
be54336
add validationID verification
iansuvak Sep 16, 2024
8096301
minor cleanup
iansuvak Sep 17, 2024
695aaff
move subnetConversion functions to helpers in utils
iansuvak Sep 17, 2024
57256e0
mock initialize validator set
Sep 17, 2024
19aa136
Merge remote-tracking branch 'origin/staking-contract' into initial-v…
Sep 17, 2024
5551db9
lint fixes
Sep 17, 2024
dac8d50
Update other tests and go mod tidy
iansuvak Sep 17, 2024
ffb7151
Merge remote-tracking branch 'origin/initial-validators-ending' into …
iansuvak Sep 17, 2024
19f4998
lint
iansuvak Sep 17, 2024
4fb66c9
update test to fix churn tracking
Sep 17, 2024
410fef4
Update contracts/staking/interfaces/IValidatorManager.sol
Sep 17, 2024
766ebdf
Update contracts/staking/ValidatorManager.sol
Sep 17, 2024
05e2cfd
fix comment
Sep 17, 2024
f03a1f1
make weight configurable for poa
iansuvak Sep 17, 2024
38aa2a2
Merge remote-tracking branch 'origin/initial-validators-ending' into …
iansuvak Sep 17, 2024
2fd7783
fix churn
iansuvak Sep 17, 2024
f1dcd6b
fix initialized validator set after migration
Sep 17, 2024
7e6cbd5
poa->pos testing fix
iansuvak Sep 17, 2024
29259c5
Merge pull request #552 from ava-labs/gstuart/native-staking-rewards
geoff-vball Sep 17, 2024
a247eeb
pre-increment fix
iansuvak Sep 17, 2024
436290b
Merge pull request #553 from ava-labs/initial-validators-ending-e2e
iansuvak Sep 17, 2024
15d9fbd
Account for validation ending before delegation
geoff-vball Sep 17, 2024
44d8097
Updates and fixes
geoff-vball Sep 18, 2024
9abff90
Move weight update to validatormanager
geoff-vball Sep 18, 2024
d0ba99e
Move weight update to validatormanager
geoff-vball Sep 18, 2024
2faa0af
Simplify churn tracking
geoff-vball Sep 18, 2024
eed92e4
Simplify churn tracking
geoff-vball Sep 18, 2024
9019085
Remove unneccessary comment
geoff-vball Sep 18, 2024
2109a68
Add comments
geoff-vball Sep 18, 2024
0eb93c6
rename newWeight and oldWeight
geoff-vball Sep 18, 2024
69242fd
Merge branch 'validation-ends-first' into staking-rewards
geoff-vball Sep 18, 2024
8d2969a
Update contracts/staking/PoSValidatorManager.sol
geoff-vball Sep 18, 2024
b465fba
Update contracts/staking/PoSValidatorManager.sol
geoff-vball Sep 18, 2024
c215b3c
Update contracts/staking/PoSValidatorManager.sol
geoff-vball Sep 18, 2024
d9ae361
fix comment
geoff-vball Sep 18, 2024
fbeb9c5
Update contracts/staking/ValidatorMessages.sol
cam-schultz Sep 18, 2024
fb872a7
fix comment
geoff-vball Sep 18, 2024
b943edc
Update contracts/staking/interfaces/IValidatorManager.sol
cam-schultz Sep 18, 2024
8e25aa2
review fixes
geoff-vball Sep 18, 2024
9bbfde2
review fixes
geoff-vball Sep 18, 2024
7d96776
Merge branch 'validation-ends-first' into staking-rewards
geoff-vball Sep 18, 2024
be8d434
lint
geoff-vball Sep 18, 2024
bda2341
Merge branch 'validation-ends-first' into staking-rewards
geoff-vball Sep 18, 2024
ebe122e
lint
geoff-vball Sep 18, 2024
32d2b9e
minor feedback
cam-schultz Sep 18, 2024
260b8a1
remove subnetConversionData validity checks
cam-schultz Sep 18, 2024
75b4b38
Merge branch 'initial-validators-ending' of github.com:ava-labs/telep…
cam-schultz Sep 18, 2024
90e33ad
build fix
cam-schultz Sep 18, 2024
6623df0
fix packing
cam-schultz Sep 18, 2024
0896ba3
Merge pull request #547 from ava-labs/initial-validators-ending
cam-schultz Sep 18, 2024
ff7163e
Merge branch 'staking-contract' into validation-ends-first
geoff-vball Sep 18, 2024
8a791c1
Merge branch 'staking-contract' into staking-rewards
geoff-vball Sep 18, 2024
56fae8b
rename staking folder to validatorManager
iansuvak Sep 18, 2024
fcaf32c
remove staking abi-bindings
iansuvak Sep 18, 2024
44807c9
update imports
iansuvak Sep 18, 2024
13e210b
Review fixes
geoff-vball Sep 18, 2024
061c125
Review fixes
geoff-vball Sep 18, 2024
3716819
rename more files
iansuvak Sep 18, 2024
19e28b3
Fix unit tests
geoff-vball Sep 18, 2024
d5e5e26
Function for withdrawing delegation fees
geoff-vball Sep 18, 2024
622e6a8
validatorManager -> validator-manager
iansuvak Sep 18, 2024
a7998b8
Merge remote-tracking branch 'origin/staking-rewards' into staking-re…
iansuvak Sep 18, 2024
c9b1556
Hook up native minter precompile to PoS tests
geoff-vball Sep 18, 2024
bc7ddc7
wait for success in AddNativeMinterAdmin
iansuvak Sep 18, 2024
9e80079
lint
iansuvak Sep 18, 2024
491ae79
Merge branch 'staking-rewards' into staking-rename
iansuvak Sep 18, 2024
015d92e
Review fixes
geoff-vball Sep 19, 2024
daad525
Check for owner when initializing validator completion
geoff-vball Sep 19, 2024
3286116
Small fix
geoff-vball Sep 19, 2024
6b1e9c0
Small fix
geoff-vball Sep 19, 2024
db44dab
Emit rewards and fees on delegator exit
geoff-vball Sep 19, 2024
49636c1
manual packing:
iansuvak Sep 19, 2024
b4ea1b3
rename more references
iansuvak Sep 19, 2024
71230b9
Merge remote-tracking branch 'origin/staking-rewards' into staking-re…
iansuvak Sep 19, 2024
099bf13
add test
geoff-vball Sep 19, 2024
2b9ff69
use constant for pchain blockchain id
Sep 19, 2024
c1de7d3
Merge pull request #534 from ava-labs/staking-rewards
geoff-vball Sep 19, 2024
22bd94a
Merge remote-tracking branch 'origin/staking-contract' into p-chain-id
Sep 19, 2024
b8d58ee
bindings
Sep 19, 2024
f01daad
Merge remote-tracking branch 'origin/staking-contract' into staking-r…
iansuvak Sep 19, 2024
4b2e326
Merge pull request #563 from ava-labs/staking-rename
iansuvak Sep 19, 2024
6c4b0f7
fix uptime get blockchain ID
Sep 19, 2024
0c7b3eb
Merge branch 'staking-contract' into iv-packing
iansuvak Sep 19, 2024
f03a6c8
Merge remote-tracking branch 'origin/staking-contract' into p-chain-id
Sep 19, 2024
ef2425c
Merge pull request #562 from ava-labs/p-chain-id
Sep 19, 2024
fd20c84
pass unit tests but exceed max contract size
iansuvak Sep 19, 2024
bc4de86
make all other pack functions use abi.encodePacked
iansuvak Sep 19, 2024
627f47b
Merge remote-tracking branch 'origin/staking-contract' into iv-packing
iansuvak Sep 19, 2024
1aa83fe
Small fixes
geoff-vball Sep 19, 2024
59a98b1
Fix e2e
geoff-vball Sep 19, 2024
ed15d98
Fix unit tests
geoff-vball Sep 19, 2024
5048225
review feedback
iansuvak Sep 19, 2024
9683e9c
Fix bug where validator exits while delegation is still pending added
geoff-vball Sep 20, 2024
4149155
Merge pull request #564 from ava-labs/iv-packing
iansuvak Sep 20, 2024
a2e817a
Merge branch 'staking-contract' into gstuart/fixups
geoff-vball Sep 20, 2024
e6e1629
validator manager custom errors
cam-schultz Sep 20, 2024
c8ee395
remove error decls from interface
cam-schultz Sep 20, 2024
bafc103
pos manager custom errors
cam-schultz Sep 20, 2024
e7ac131
update abi
cam-schultz Sep 20, 2024
329d1e7
Merge branch 'staking-contract' into custom-errors
cam-schultz Sep 20, 2024
059aee3
Update contracts/validator-manager/PoSValidatorManager.sol
cam-schultz Sep 20, 2024
6a80d63
comment type
cam-schultz Sep 20, 2024
556c147
Fix bug where delegator can't exit after validation has ended
geoff-vball Sep 20, 2024
4b00073
cleanup
geoff-vball Sep 20, 2024
396bf4c
Fix delegator end time
geoff-vball Sep 20, 2024
b61841d
consistent types
cam-schultz Sep 20, 2024
315ee62
update bindings
cam-schultz Sep 20, 2024
69cf948
reference custom errors directly
cam-schultz Sep 20, 2024
1793727
validator messages custom errors
cam-schultz Sep 20, 2024
64700da
Fixups
geoff-vball Sep 20, 2024
d0b3724
fix comment
geoff-vball Sep 20, 2024
5d1be58
Add check
geoff-vball Sep 20, 2024
d9b18da
pre-increment
michaelkaplan13 Sep 20, 2024
0eaeea8
Fix abi bindings
michaelkaplan13 Sep 20, 2024
d7367d6
Remove Delegator.endedAt
geoff-vball Sep 20, 2024
f73d2d0
format + lint
cam-schultz Sep 20, 2024
c54321c
Merge pull request #566 from ava-labs/custom-errors
cam-schultz Sep 20, 2024
9a17f4c
Merge branch 'staking-contract' into gstuart/fixups
geoff-vball Sep 20, 2024
8c27c5a
update vdr manager readme
cam-schultz Sep 20, 2024
f3a6194
clarification
cam-schultz Sep 20, 2024
09e69d7
Merge pull request #565 from ava-labs/gstuart/fixups
geoff-vball Sep 20, 2024
855eb00
Merge pull request #567 from ava-labs/update-readme
cam-schultz Sep 20, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,356 changes: 1,356 additions & 0 deletions abi-bindings/go/staking/ERC20TokenStakingManager/ERC20TokenStakingManager.go

Large diffs are not rendered by default.

1,356 changes: 1,356 additions & 0 deletions abi-bindings/go/staking/NativeTokenStakingManager/NativeTokenStakingManager.go

Large diffs are not rendered by default.

1,366 changes: 1,366 additions & 0 deletions abi-bindings/go/staking/PoAValidatorManager/PoAValidatorManager.go

Large diffs are not rendered by default.

98 changes: 98 additions & 0 deletions contracts/staking/ERC20TokenStakingManager.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
// (c) 2024, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

// SPDX-License-Identifier: Ecosystem

pragma solidity 0.8.25;

import {IERC20TokenStakingManager} from "./interfaces/IERC20TokenStakingManager.sol";
import {Initializable} from
"@openzeppelin/[email protected]/proxy/utils/Initializable.sol";
import {IERC20} from "@openzeppelin/[email protected]/token/ERC20/IERC20.sol";
import {SafeERC20TransferFrom} from "@utilities/SafeERC20TransferFrom.sol";
import {SafeERC20} from "@openzeppelin/[email protected]/token/ERC20/utils/SafeERC20.sol";
import {ICMInitializable} from "../utilities/ICMInitializable.sol";
import {PoSValidatorManager} from "./PoSValidatorManager.sol";
import {PoSValidatorManagerSettings} from "./interfaces/IPoSValidatorManager.sol";

contract ERC20TokenStakingManager is
Initializable,
PoSValidatorManager,
IERC20TokenStakingManager
{
using SafeERC20 for IERC20;
using SafeERC20TransferFrom for IERC20;

// solhint-disable private-vars-leading-underscore
/// @custom:storage-location erc7201:avalanche-icm.storage.ERC20TokenStakingManager
struct ERC20TokenStakingManagerStorage {
IERC20 _token;
uint8 _tokenDecimals;
}
// solhint-enable private-vars-leading-underscore

// keccak256(abi.encode(uint256(keccak256("avalanche-icm.storage.ERC20TokenStakingManager")) - 1)) & ~bytes32(uint256(0xff));
// TODO: Update to correct storage slot
bytes32 private constant _ERC20_STAKING_MANAGER_STORAGE_LOCATION =
0x6e5bdfcce15e53c3406ea67bfce37dcd26f5152d5492824e43fd5e3c8ac5ab00;

// solhint-disable ordering
function _getERC20StakingManagerStorage()
private
pure
returns (ERC20TokenStakingManagerStorage storage $)
{
// solhint-disable-next-line no-inline-assembly
assembly {
$.slot := _ERC20_STAKING_MANAGER_STORAGE_LOCATION
}
}

constructor(ICMInitializable init) {
if (init == ICMInitializable.Disallowed) {
_disableInitializers();
}
}

function initialize(
PoSValidatorManagerSettings calldata settings,
IERC20 token
) external initializer {
__ERC20TokenStakingManager_init(settings, token);
}

// solhint-disable func-name-mixedcase
function __ERC20TokenStakingManager_init(
PoSValidatorManagerSettings calldata settings,
IERC20 token
) internal onlyInitializing {
__POS_Validator_Manager_init(settings);
__ERC20TokenStakingManager_init_unchained(token);
}

Check warning

Code scanning / Slither

Conformance to Solidity naming conventions

Function ERC20TokenStakingManager.__ERC20TokenStakingManager_init(PoSValidatorManagerSettings,IERC20) (contracts/staking/ERC20TokenStakingManager.sol#65-71) is not in mixedCase

// solhint-disable func-name-mixedcase
function __ERC20TokenStakingManager_init_unchained(IERC20 token) internal onlyInitializing {
ERC20TokenStakingManagerStorage storage $ = _getERC20StakingManagerStorage();
require(address(token) != address(0), "ERC20TokenStakingManager: zero token address");
$._token = token;
}

function initializeValidatorRegistration(
uint256 stakeAmount,
bytes32 nodeID,
uint64 registrationExpiry,
bytes memory blsPublicKey
) external override returns (bytes32 validationID) {
uint64 weight = _processStake(stakeAmount);
return _initializeValidatorRegistration(nodeID, weight, registrationExpiry, blsPublicKey);
}

// Must be guarded with reentrancy guard for safe transfer from
function _lock(uint256 value) internal virtual override returns (uint256) {
return _getERC20StakingManagerStorage()._token.safeTransferFrom(value);
}

function _unlock(uint256 value, address to) internal virtual override {
_getERC20StakingManagerStorage()._token.safeTransfer(to, value);
}
}
31 changes: 31 additions & 0 deletions contracts/staking/ExampleRewardCalculator.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// (c) 2024, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

// SPDX-License-Identifier: Ecosystem

pragma solidity 0.8.25;

import {IRewardCalculator} from "./interfaces/IRewardCalculator.sol";

contract ExampleRewardCalculator is IRewardCalculator {
uint256 public constant SECONDS_IN_YEAR = 31536000;

uint64 public immutable rewardBasisPoints;

constructor(uint64 rewardBasisPoints_) {
rewardBasisPoints = rewardBasisPoints_;
}

/**
* @notice A linear, non-compounding reward calculation that rewards a set percentage of tokens per year.
*/
function calculateReward(
uint256 stakeAmount,
uint64 startTime,
uint64 endTime,
uint256, // initialSupply
uint256 // endSupply
) external view returns (uint256) {
return (stakeAmount * rewardBasisPoints * (endTime - startTime)) / SECONDS_IN_YEAR / 1000;
}
}
74 changes: 74 additions & 0 deletions contracts/staking/NativeTokenStakingManager.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// (c) 2024, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

// SPDX-License-Identifier: Ecosystem
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(nit) Confirm with a lawyer, but I think this should be UNLICENSED per Solidity conventions for non-OSS licenses (not UNLICENSE without the D). There are specific license identifiers for SPDX.


pragma solidity 0.8.25;

import {INativeTokenStakingManager} from "./interfaces/INativeTokenStakingManager.sol";
import {Address} from "@openzeppelin/[email protected]/utils/Address.sol";
import {Initializable} from
"@openzeppelin/[email protected]/proxy/utils/Initializable.sol";
import {ICMInitializable} from "../utilities/ICMInitializable.sol";
import {PoSValidatorManager} from "./PoSValidatorManager.sol";
import {PoSValidatorManagerSettings} from "./interfaces/IPoSValidatorManager.sol";

contract NativeTokenStakingManager is
Initializable,
PoSValidatorManager,
INativeTokenStakingManager
{
using Address for address payable;

constructor(ICMInitializable init) {
if (init == ICMInitializable.Disallowed) {
_disableInitializers();
}
}

// solhint-disable ordering
function initialize(PoSValidatorManagerSettings calldata settings) external initializer {
__NativeTokenStakingManager_init(settings);
}

// solhint-disable-next-line func-name-mixedcase
function __NativeTokenStakingManager_init(PoSValidatorManagerSettings calldata settings)
internal
onlyInitializing
{
__POS_Validator_Manager_init(settings);
}

Check warning

Code scanning / Slither

Conformance to Solidity naming conventions

Function NativeTokenStakingManager.__NativeTokenStakingManager_init(PoSValidatorManagerSettings) (contracts/staking/NativeTokenStakingManager.sol#35-40) is not in mixedCase

// solhint-disable-next-line func-name-mixedcase, no-empty-blocks
function __NativeTokenStakingManager_init_unchained() internal onlyInitializing {}

/**
* @notice Begins the validator registration process. Locks the provided native asset in the contract as the stake.
* @param nodeID The node ID of the validator being registered.
* @param registrationExpiry The time at which the registration is no longer valid on the P-Chain.
* @param signature The raw bytes of the Ed25519 signature over the concatenated bytes of
* [subnetID]+[nodeID]+[blsPublicKey]+[weight]+[balance]+[expiry]. This signature must correspond to the Ed25519
* public key that is used for the nodeID. This approach prevents nodeIDs from being unwillingly added to Subnets.
* balance is the minimum initial $nAVAX balance that must be attached to the validator serialized as a uint64.
* The signature field will be validated by the P-Chain. Implementations may choose to validate that the signature
* field is well-formed but it is not required.
*/
function initializeValidatorRegistration(
bytes32 nodeID,
uint64 registrationExpiry,
bytes memory signature
) external payable returns (bytes32) {
uint64 weight = _processStake(msg.value);

return _initializeValidatorRegistration(nodeID, weight, registrationExpiry, signature);
}

// solhint-enable ordering
function _lock(uint256 value) internal virtual override returns (uint256) {
return value;
}

function _unlock(uint256 value, address to) internal virtual override {
payable(to).sendValue(value);
}

Check warning

Code scanning / Slither

Dead-code

NativeTokenStakingManager._unlock(uint256,address) (contracts/staking/NativeTokenStakingManager.sol#38-40) is never used and should be removed
}
56 changes: 56 additions & 0 deletions contracts/staking/PoAValidatorManager.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// (c) 2024, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

// SPDX-License-Identifier: Ecosystem

pragma solidity 0.8.25;

import {IPoAValidatorManager} from "./interfaces/IPoAValidatorManager.sol";
import {OwnableUpgradeable} from
"@openzeppelin/[email protected]/access/OwnableUpgradeable.sol";
import {ICMInitializable} from "../utilities/ICMInitializable.sol";
import {ValidatorManagerSettings} from "./interfaces/IValidatorManager.sol";
import {ValidatorManager} from "./ValidatorManager.sol";

contract PoAValidatorManager is IPoAValidatorManager, ValidatorManager, OwnableUpgradeable {
constructor(ICMInitializable init) {
if (init == ICMInitializable.Disallowed) {
_disableInitializers();
}
}

function initialize(
ValidatorManagerSettings calldata settings,
address initialOwner
) external initializer {
__PoAValidatorManager_init(settings, initialOwner);
}

// solhint-disable func-name-mixedcase, ordering
function __PoAValidatorManager_init(
ValidatorManagerSettings calldata settings,
address initialOwner
) internal onlyInitializing {
__ValidatorManager_init(settings);
__Ownable_init(initialOwner);
}

Check warning

Code scanning / Slither

Conformance to Solidity naming conventions

Function PoAValidatorManager.__PoAValidatorManager_init(ValidatorManagerSettings,address) (contracts/staking/PoAValidatorManager.sol#30-36) is not in mixedCase

// solhint-disable-next-line no-empty-blocks
function __PoAValidatorManager_init_unchained() internal onlyInitializing {}

Check warning

Code scanning / Slither

Dead-code

PoAValidatorManager.__PoAValidatorManager_init_unchained() (contracts/staking/PoAValidatorManager.sol#39) is never used and should be removed

Check warning

Code scanning / Slither

Conformance to Solidity naming conventions

Function PoAValidatorManager.__PoAValidatorManager_init_unchained() (contracts/staking/PoAValidatorManager.sol#39) is not in mixedCase

// solhint-enable func-name-mixedcase

function initializeValidatorRegistration(
uint64 weight,
bytes32 nodeID,
uint64 registrationExpiry,
bytes memory signature
) external override onlyOwner returns (bytes32 validationID) {
return _initializeValidatorRegistration(nodeID, weight, registrationExpiry, signature);
}

// solhint-enable ordering
function initializeEndValidation(bytes32 validationID) external override {
_initializeEndValidation(validationID);
}
}
133 changes: 133 additions & 0 deletions contracts/staking/PoSValidatorManager.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
// (c) 2024, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

// SPDX-License-Identifier: Ecosystem

pragma solidity 0.8.25;

import {IPoSValidatorManager} from "./interfaces/IPoSValidatorManager.sol";
import {PoSValidatorManagerSettings} from "./interfaces/IPoSValidatorManager.sol";
import {ValidatorManager} from "./ValidatorManager.sol";
import {WarpMessage} from
"@avalabs/[email protected]/contracts/interfaces/IWarpMessenger.sol";
import {ValidatorMessages} from "./ValidatorMessages.sol";
import {IRewardCalculator} from "./interfaces/IRewardCalculator.sol";

abstract contract PoSValidatorManager is IPoSValidatorManager, ValidatorManager {
// solhint-disable private-vars-leading-underscore
/// @custom:storage-location erc7201:avalanche-icm.storage.PoSValidatorManager
struct PoSValidatorManagerStorage {
uint256 _minimumStakeAmount;
uint256 _maximumStakeAmount;
uint64 _minimumStakeDuration;
IRewardCalculator _rewardCalculator;
mapping(bytes32 validationID => uint64) _validatorUptimes;
}
// solhint-enable private-vars-leading-underscore

// keccak256(abi.encode(uint256(keccak256("avalanche-icm.storage.PoSValidatorManager")) - 1)) & ~bytes32(uint256(0xff));
// TODO: Unit test for storage slot and update slot
bytes32 private constant _POS_VALIDATOR_MANAGER_STORAGE_LOCATION =
0x4317713f7ecbdddd4bc99e95d903adedaa883b2e7c2551610bd13e2c7e473d00;

// solhint-disable ordering
function _getPoSValidatorManagerStorage()
private
pure
returns (PoSValidatorManagerStorage storage $)
{
// solhint-disable-next-line no-inline-assembly
assembly {
$.slot := _POS_VALIDATOR_MANAGER_STORAGE_LOCATION
}
}

Check warning

Code scanning / Slither

Assembly usage

PoSValidatorManager._getPoSValidatorManagerStorage() (contracts/staking/PoSValidatorManager.sol#34-43) uses assembly - INLINE ASM (contracts/staking/PoSValidatorManager.sol#40-42)

// solhint-disable-next-line func-name-mixedcase
function __POS_Validator_Manager_init(PoSValidatorManagerSettings calldata settings)
internal
onlyInitializing
{
__ValidatorManager_init(settings.baseSettings);
__POS_Validator_Manager_init_unchained(
settings.minimumStakeAmount,
settings.maximumStakeAmount,
settings.minimumStakeDuration,
settings.rewardCalculator
);
}

Check warning

Code scanning / Slither

Conformance to Solidity naming conventions

Function PoSValidatorManager.__POS_Validator_Manager_init(PoSValidatorManagerSettings) (contracts/staking/PoSValidatorManager.sol#46-57) is not in mixedCase

// solhint-disable-next-line func-name-mixedcase
function __POS_Validator_Manager_init_unchained(
uint256 minimumStakeAmount,
uint256 maximumStakeAmount,
uint64 minimumStakeDuration,
IRewardCalculator rewardCalculator
) internal onlyInitializing {
PoSValidatorManagerStorage storage s = _getPoSValidatorManagerStorage();
s._minimumStakeAmount = minimumStakeAmount;
s._maximumStakeAmount = maximumStakeAmount;
s._minimumStakeDuration = minimumStakeDuration;
s._rewardCalculator = rewardCalculator;
}

Check warning

Code scanning / Slither

Conformance to Solidity naming conventions

Function PoSValidatorManager.__POS_Validator_Manager_init_unchained(uint256,uint256,uint64,IRewardCalculator) (contracts/staking/PoSValidatorManager.sol#60-71) is not in mixedCase

function initializeEndValidation(
bytes32 validationID,
bool includeUptimeProof,
uint32 messageIndex
) external {
if (includeUptimeProof) {
PoSValidatorManagerStorage storage $ = _getPoSValidatorManagerStorage();
(WarpMessage memory warpMessage, bool valid) =
WARP_MESSENGER.getVerifiedWarpMessage(messageIndex);
require(valid, "PoSValidatorManager: invalid warp message");

require(
warpMessage.sourceChainID == WARP_MESSENGER.getBlockchainID(),
"PoSValidatorManager: invalid source chain ID"
);
require(
warpMessage.originSenderAddress == address(0),
"PoSValidatorManager: invalid origin sender address"
);

(bytes32 uptimeValidationID, uint64 uptime) =
ValidatorMessages.unpackValidationUptimeMessage(warpMessage.payload);
require(
validationID == uptimeValidationID,
"PoSValidatorManager: invalid uptime validation ID"
);

$._validatorUptimes[validationID] = uptime;
emit ValidationUptimeUpdated(validationID, uptime);
}

_initializeEndValidation(validationID);
}

function _processStake(uint256 stakeAmount) internal virtual returns (uint64) {
PoSValidatorManagerStorage storage $ = _getPoSValidatorManagerStorage();
// Lock the stake in the contract.
uint256 lockedValue = _lock(stakeAmount);

// Ensure the stake churn doesn't exceed the maximum churn rate.
uint64 weight = valueToWeight(lockedValue);
// Ensure the weight is within the valid range.

require(
weight >= $._minimumStakeAmount && weight <= $._maximumStakeAmount,
"PoSValidatorManager: invalid stake amount"
);
return weight;
}

function valueToWeight(uint256 value) public pure returns (uint64) {
return uint64(value / 1e12);
}

function weightToValue(uint64 weight) public pure returns (uint256) {
return uint256(weight) * 1e12;
}

function _lock(uint256 value) internal virtual returns (uint256);
function _unlock(uint256 value, address to) internal virtual;
}
Loading