@evvm/testnet-contracts 2.2.3 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +145 -118
- package/README.md +162 -39
- package/contracts/core/Core.sol +1394 -0
- package/contracts/core/lib/CoreStorage.sol +171 -0
- package/contracts/nameService/NameService.sol +666 -586
- package/contracts/nameService/lib/IdentityValidation.sol +18 -3
- package/contracts/p2pSwap/P2PSwap.sol +439 -285
- package/contracts/staking/Estimator.sol +128 -40
- package/contracts/staking/Staking.sol +329 -322
- package/contracts/treasury/Treasury.sol +48 -37
- package/contracts/treasuryTwoChains/TreasuryExternalChainStation.sol +585 -198
- package/contracts/treasuryTwoChains/TreasuryHostChainStation.sol +425 -174
- package/contracts/treasuryTwoChains/lib/PayloadUtils.sol +2 -4
- package/interfaces/{IEvvm.sol → ICore.sol} +67 -29
- package/interfaces/IEstimator.sol +1 -1
- package/interfaces/INameService.sol +58 -52
- package/interfaces/IP2PSwap.sol +18 -17
- package/interfaces/IStaking.sol +22 -17
- package/interfaces/ITreasury.sol +2 -1
- package/interfaces/ITreasuryExternalChainStation.sol +15 -9
- package/interfaces/ITreasuryHostChainStation.sol +14 -11
- package/interfaces/IUserValidator.sol +6 -0
- package/library/Erc191TestBuilder.sol +350 -297
- package/library/EvvmService.sol +38 -27
- package/library/errors/CoreError.sol +116 -0
- package/library/errors/CrossChainTreasuryError.sol +36 -0
- package/library/errors/NameServiceError.sol +79 -0
- package/library/errors/StakingError.sol +79 -0
- package/library/errors/TreasuryError.sol +33 -0
- package/library/primitives/SignatureRecover.sol +33 -0
- package/library/structs/CoreStructs.sol +146 -0
- package/library/structs/ExternalChainStationStructs.sol +92 -0
- package/library/structs/HostChainStationStructs.sol +77 -0
- package/library/structs/NameServiceStructs.sol +47 -0
- package/library/structs/P2PSwapStructs.sol +127 -0
- package/library/structs/StakingStructs.sol +67 -0
- package/library/utils/AdvancedStrings.sol +84 -5
- package/library/utils/CAUtils.sol +29 -0
- package/library/utils/SignatureUtil.sol +34 -0
- package/library/utils/governance/Admin.sol +66 -0
- package/library/utils/governance/ProposalStructs.sol +49 -0
- package/library/utils/service/CoreExecution.sol +177 -0
- package/library/utils/service/StakingServiceUtils.sol +30 -3
- package/library/utils/signature/CoreHashUtils.sol +73 -0
- package/library/utils/signature/NameServiceHashUtils.sol +156 -0
- package/library/utils/signature/P2PSwapHashUtils.sol +65 -0
- package/library/utils/signature/StakingHashUtils.sol +41 -0
- package/library/utils/signature/TreasuryCrossChainHashUtils.sol +40 -0
- package/package.json +2 -1
- package/contracts/evvm/Evvm.sol +0 -1327
- package/contracts/evvm/lib/ErrorsLib.sol +0 -18
- package/contracts/evvm/lib/EvvmStorage.sol +0 -62
- package/contracts/evvm/lib/EvvmStructs.sol +0 -90
- package/contracts/evvm/lib/SignatureUtils.sol +0 -120
- package/contracts/nameService/lib/ErrorsLib.sol +0 -21
- package/contracts/nameService/lib/NameServiceStructs.sol +0 -69
- package/contracts/nameService/lib/SignatureUtils.sol +0 -245
- package/contracts/p2pSwap/lib/P2PSwapStructs.sol +0 -59
- package/contracts/p2pSwap/lib/SignatureUtils.sol +0 -98
- package/contracts/staking/lib/ErrorsLib.sol +0 -22
- package/contracts/staking/lib/SignatureUtils.sol +0 -39
- package/contracts/staking/lib/StakingStructs.sol +0 -94
- package/contracts/treasury/lib/ErrorsLib.sol +0 -11
- package/contracts/treasuryTwoChains/lib/ErrorsLib.sol +0 -48
- package/contracts/treasuryTwoChains/lib/ExternalChainStationStructs.sol +0 -80
- package/contracts/treasuryTwoChains/lib/HostChainStationStructs.sol +0 -87
- package/contracts/treasuryTwoChains/lib/SignatureUtils.sol +0 -79
- package/library/utils/GovernanceUtils.sol +0 -81
- package/library/utils/nonces/AsyncNonce.sol +0 -32
- package/library/utils/nonces/SyncNonce.sol +0 -27
- package/library/utils/service/EvvmPayments.sol +0 -79
|
@@ -2,6 +2,26 @@
|
|
|
2
2
|
// Full license terms available at: https://www.evvm.info/docs/EVVMNoncommercialLicense
|
|
3
3
|
|
|
4
4
|
pragma solidity ^0.8.0;
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
StakingError as Error
|
|
8
|
+
} from "@evvm/testnet-contracts/library/errors/StakingError.sol";
|
|
9
|
+
import {
|
|
10
|
+
StakingHashUtils as Hash
|
|
11
|
+
} from "@evvm/testnet-contracts/library/utils/signature/StakingHashUtils.sol";
|
|
12
|
+
import {
|
|
13
|
+
StakingStructs as Structs
|
|
14
|
+
} from "@evvm/testnet-contracts/library/structs/StakingStructs.sol";
|
|
15
|
+
|
|
16
|
+
import {Core} from "@evvm/testnet-contracts/contracts/core/Core.sol";
|
|
17
|
+
import {
|
|
18
|
+
Estimator
|
|
19
|
+
} from "@evvm/testnet-contracts/contracts/staking/Estimator.sol";
|
|
20
|
+
|
|
21
|
+
import {
|
|
22
|
+
ProposalStructs
|
|
23
|
+
} from "@evvm/testnet-contracts/library/utils/governance/ProposalStructs.sol";
|
|
24
|
+
|
|
5
25
|
/**
|
|
6
26
|
|
|
7
27
|
|
|
@@ -23,32 +43,14 @@ pragma solidity ^0.8.0;
|
|
|
23
43
|
██║ ██╔══╝ ╚════██║ ██║ ██║╚██╗██║██╔══╝ ██║
|
|
24
44
|
██║ ███████╗███████║ ██║ ██║ ╚████║███████╗ ██║
|
|
25
45
|
╚═╝ ╚══════╝╚══════╝ ╚═╝ ╚═╝ ╚═══╝╚══════╝ ╚═╝
|
|
26
|
-
* @title Staking
|
|
46
|
+
* @title EVVM Staking
|
|
27
47
|
* @author Mate labs
|
|
28
|
-
* @notice
|
|
29
|
-
* @dev
|
|
30
|
-
*
|
|
31
|
-
* The contract supports three types of staking:
|
|
32
|
-
* 1. Golden Staking: Exclusive to the goldenFisher address
|
|
33
|
-
* 2. Presale Staking: Limited to 800 presale users with 2 staking token limit
|
|
34
|
-
* 3. Public Staking: Open to all users when enabled
|
|
35
|
-
* 4. Service Staking: Allows smart contracts to stake on behalf of users
|
|
36
|
-
*
|
|
37
|
-
* Key features:
|
|
38
|
-
* - Time-locked unstaking mechanisms
|
|
39
|
-
* - Signature-based authorization
|
|
40
|
-
* - Integration with EVVM core contract for payments and rewards
|
|
41
|
-
* - Estimator integration for yield calculations
|
|
48
|
+
* @notice Validator staking mechanism for the EVVM ecosystem.
|
|
49
|
+
* @dev Manages staking, unstaking, and yield distribution via the Estimator contract.
|
|
50
|
+
* Supports presale and public staking phases with time-locked security and nonce-based replay protection.
|
|
42
51
|
*/
|
|
43
52
|
|
|
44
|
-
|
|
45
|
-
import {IEstimator} from "@evvm/testnet-contracts/interfaces/IEstimator.sol";
|
|
46
|
-
import {AsyncNonce} from "@evvm/testnet-contracts/library/utils/nonces/AsyncNonce.sol";
|
|
47
|
-
import {StakingStructs} from "@evvm/testnet-contracts/contracts/staking/lib/StakingStructs.sol";
|
|
48
|
-
import {ErrorsLib} from "./lib/ErrorsLib.sol";
|
|
49
|
-
import {SignatureUtils} from "./lib/SignatureUtils.sol";
|
|
50
|
-
|
|
51
|
-
contract Staking is AsyncNonce, StakingStructs {
|
|
53
|
+
contract Staking {
|
|
52
54
|
uint256 constant TIME_TO_ACCEPT_PROPOSAL = 1 days;
|
|
53
55
|
|
|
54
56
|
/// @dev Address of the EVVM core contract
|
|
@@ -61,42 +63,38 @@ contract Staking is AsyncNonce, StakingStructs {
|
|
|
61
63
|
/// @dev Price of one staking main token (5083 main token = 1 staking)
|
|
62
64
|
uint256 private constant PRICE_OF_STAKING = 5083 * (10 ** 18);
|
|
63
65
|
|
|
64
|
-
/// @dev Address representing the principal Principal Token
|
|
65
|
-
address private constant PRINCIPAL_TOKEN_ADDRESS =
|
|
66
|
-
0x0000000000000000000000000000000000000001;
|
|
67
|
-
|
|
68
66
|
/// @dev Admin address management with proposal system
|
|
69
|
-
AddressTypeProposal private admin;
|
|
67
|
+
ProposalStructs.AddressTypeProposal private admin;
|
|
70
68
|
/// @dev Golden Fisher address management with proposal system
|
|
71
|
-
AddressTypeProposal private goldenFisher;
|
|
69
|
+
ProposalStructs.AddressTypeProposal private goldenFisher;
|
|
72
70
|
/// @dev Estimator contract address management with proposal system
|
|
73
|
-
AddressTypeProposal private estimatorAddress;
|
|
71
|
+
ProposalStructs.AddressTypeProposal private estimatorAddress;
|
|
74
72
|
/// @dev Time delay for regular staking after unstaking
|
|
75
|
-
UintTypeProposal private secondsToUnlockStaking;
|
|
73
|
+
ProposalStructs.UintTypeProposal private secondsToUnlockStaking;
|
|
76
74
|
/// @dev Time delay for full unstaking (21 days default)
|
|
77
|
-
UintTypeProposal private secondsToUnllockFullUnstaking;
|
|
75
|
+
ProposalStructs.UintTypeProposal private secondsToUnllockFullUnstaking;
|
|
78
76
|
/// @dev Flag to enable/disable presale staking
|
|
79
|
-
BoolTypeProposal private allowPresaleStaking;
|
|
77
|
+
ProposalStructs.BoolTypeProposal private allowPresaleStaking;
|
|
80
78
|
/// @dev Flag to enable/disable public staking
|
|
81
|
-
BoolTypeProposal private allowPublicStaking;
|
|
79
|
+
ProposalStructs.BoolTypeProposal private allowPublicStaking;
|
|
82
80
|
/// @dev Variable to store service staking metadata
|
|
83
|
-
ServiceStakingMetadata private serviceStakingData;
|
|
81
|
+
Structs.ServiceStakingMetadata private serviceStakingData;
|
|
84
82
|
|
|
85
83
|
/// @dev One-time setup breaker for estimator and EVVM addresses
|
|
86
84
|
bytes1 private breakerSetupEstimatorAndEvvm;
|
|
87
85
|
|
|
88
86
|
/// @dev Mapping to store presale staker metadata
|
|
89
|
-
mapping(address =>
|
|
87
|
+
mapping(address => Structs.PresaleStakerMetadata) private userPresaleStaker;
|
|
90
88
|
|
|
91
89
|
/// @dev Mapping to store complete staking history for each user
|
|
92
|
-
mapping(address => HistoryMetadata[]) private userHistory;
|
|
90
|
+
mapping(address => Structs.HistoryMetadata[]) private userHistory;
|
|
93
91
|
|
|
94
|
-
|
|
95
|
-
|
|
92
|
+
Core private core;
|
|
93
|
+
Estimator private estimator;
|
|
96
94
|
|
|
97
95
|
/// @dev Modifier to verify access to admin functions
|
|
98
96
|
modifier onlyOwner() {
|
|
99
|
-
if (msg.sender != admin.
|
|
97
|
+
if (msg.sender != admin.current) revert Error.SenderIsNotAdmin();
|
|
100
98
|
|
|
101
99
|
_;
|
|
102
100
|
}
|
|
@@ -111,297 +109,293 @@ contract Staking is AsyncNonce, StakingStructs {
|
|
|
111
109
|
size := extcodesize(callerAddress)
|
|
112
110
|
}
|
|
113
111
|
|
|
114
|
-
if (size == 0) revert
|
|
112
|
+
if (size == 0) revert Error.AddressIsNotAService();
|
|
115
113
|
|
|
116
114
|
_;
|
|
117
115
|
}
|
|
118
116
|
|
|
119
117
|
/**
|
|
120
|
-
* @notice
|
|
121
|
-
* @
|
|
122
|
-
* @param
|
|
123
|
-
* @param initialGoldenFisher Address that will have golden fisher privileges
|
|
118
|
+
* @notice Initializes the staking contract.
|
|
119
|
+
* @param initialAdmin System administrator.
|
|
120
|
+
* @param initialGoldenFisher Authorized Golden Fisher address.
|
|
124
121
|
*/
|
|
125
122
|
constructor(address initialAdmin, address initialGoldenFisher) {
|
|
126
|
-
admin.
|
|
123
|
+
admin.current = initialAdmin;
|
|
127
124
|
|
|
128
|
-
goldenFisher.
|
|
125
|
+
goldenFisher.current = initialGoldenFisher;
|
|
129
126
|
|
|
130
|
-
allowPublicStaking.flag =
|
|
131
|
-
allowPresaleStaking.flag =
|
|
127
|
+
allowPublicStaking.flag = true;
|
|
128
|
+
allowPresaleStaking.flag = false;
|
|
132
129
|
|
|
133
|
-
secondsToUnlockStaking.
|
|
130
|
+
secondsToUnlockStaking.current = 0;
|
|
134
131
|
|
|
135
|
-
secondsToUnllockFullUnstaking.
|
|
132
|
+
secondsToUnllockFullUnstaking.current = 5 days;
|
|
136
133
|
|
|
137
134
|
breakerSetupEstimatorAndEvvm = 0x01;
|
|
138
135
|
}
|
|
139
136
|
|
|
140
137
|
/**
|
|
141
|
-
* @notice
|
|
142
|
-
* @
|
|
143
|
-
* @param
|
|
144
|
-
* @param _evvm Address of the EVVM core contract
|
|
138
|
+
* @notice Configures system contract integrations once.
|
|
139
|
+
* @param _estimator Estimator contract address (yield calculations).
|
|
140
|
+
* @param _core EVVM Core contract address (payments).
|
|
145
141
|
*/
|
|
146
|
-
function
|
|
142
|
+
function initializeSystemContracts(
|
|
147
143
|
address _estimator,
|
|
148
|
-
address
|
|
144
|
+
address _core
|
|
149
145
|
) external {
|
|
150
146
|
if (breakerSetupEstimatorAndEvvm == 0x00) revert();
|
|
151
147
|
|
|
152
|
-
estimatorAddress.
|
|
153
|
-
EVVM_ADDRESS =
|
|
148
|
+
estimatorAddress.current = _estimator;
|
|
149
|
+
EVVM_ADDRESS = _core;
|
|
150
|
+
|
|
151
|
+
core = Core(_core);
|
|
152
|
+
estimator = Estimator(_estimator);
|
|
154
153
|
breakerSetupEstimatorAndEvvm = 0x00;
|
|
155
|
-
evvm = IEvvm(_evvm);
|
|
156
|
-
estimator = IEstimator(_estimator);
|
|
157
154
|
}
|
|
158
155
|
|
|
159
156
|
/**
|
|
160
|
-
* @notice
|
|
161
|
-
* @dev
|
|
162
|
-
* @param isStaking True
|
|
163
|
-
* @param amountOfStaking
|
|
164
|
-
* @param
|
|
157
|
+
* @notice Unlimited staking/unstaking for the Golden Fisher.
|
|
158
|
+
* @dev Uses sync nonces for coordination with Core operations.
|
|
159
|
+
* @param isStaking True to stake, false to unstake.
|
|
160
|
+
* @param amountOfStaking Number of staking tokens.
|
|
161
|
+
* @param signaturePay Authorization signature for Core payment.
|
|
165
162
|
*/
|
|
166
163
|
function goldenStaking(
|
|
167
164
|
bool isStaking,
|
|
168
165
|
uint256 amountOfStaking,
|
|
169
|
-
bytes memory
|
|
166
|
+
bytes memory signaturePay
|
|
170
167
|
) external {
|
|
171
|
-
if (msg.sender != goldenFisher.
|
|
172
|
-
revert
|
|
168
|
+
if (msg.sender != goldenFisher.current)
|
|
169
|
+
revert Error.SenderIsNotGoldenFisher();
|
|
173
170
|
|
|
174
171
|
stakingBaseProcess(
|
|
175
|
-
AccountMetadata({
|
|
172
|
+
Structs.AccountMetadata({
|
|
173
|
+
Address: goldenFisher.current,
|
|
174
|
+
IsAService: false
|
|
175
|
+
}),
|
|
176
176
|
isStaking,
|
|
177
177
|
amountOfStaking,
|
|
178
178
|
0,
|
|
179
|
-
|
|
179
|
+
core.getNextCurrentSyncNonce(msg.sender),
|
|
180
180
|
false,
|
|
181
|
-
|
|
181
|
+
signaturePay
|
|
182
182
|
);
|
|
183
183
|
}
|
|
184
184
|
|
|
185
185
|
/**
|
|
186
|
-
* @notice
|
|
187
|
-
* @
|
|
188
|
-
* @param
|
|
189
|
-
* @param
|
|
190
|
-
* @param
|
|
191
|
-
* @param
|
|
192
|
-
* @param
|
|
193
|
-
* @param
|
|
194
|
-
* @param priorityFlag_EVVM True for async EVVM transaction, false for sync
|
|
195
|
-
* @param signature_EVVM Signature for the EVVM contract transaction
|
|
186
|
+
* @notice White-listed presale staking (max 2 tokens per user).
|
|
187
|
+
* @param user Participant address.
|
|
188
|
+
* @param isStaking True to stake, false to unstake.
|
|
189
|
+
* @param nonce Async nonce for signature verification.
|
|
190
|
+
* @param signature Participant's authorization signature.
|
|
191
|
+
* @param priorityFeePay Optional priority fee.
|
|
192
|
+
* @param noncePay Nonce for the Core payment.
|
|
193
|
+
* @param signaturePay Signature for the Core payment.
|
|
196
194
|
*/
|
|
197
195
|
function presaleStaking(
|
|
198
196
|
address user,
|
|
199
197
|
bool isStaking,
|
|
198
|
+
address originExecutor,
|
|
200
199
|
uint256 nonce,
|
|
201
200
|
bytes memory signature,
|
|
202
|
-
uint256
|
|
203
|
-
uint256
|
|
204
|
-
|
|
205
|
-
bytes memory signature_EVVM
|
|
201
|
+
uint256 priorityFeePay,
|
|
202
|
+
uint256 noncePay,
|
|
203
|
+
bytes memory signaturePay
|
|
206
204
|
) external {
|
|
207
|
-
if (
|
|
208
|
-
|
|
209
|
-
evvm.getEvvmID(),
|
|
210
|
-
user,
|
|
211
|
-
false,
|
|
212
|
-
isStaking,
|
|
213
|
-
1,
|
|
214
|
-
nonce,
|
|
215
|
-
signature
|
|
216
|
-
)
|
|
217
|
-
) revert ErrorsLib.InvalidSignatureOnStaking();
|
|
205
|
+
if (!allowPresaleStaking.flag || allowPublicStaking.flag)
|
|
206
|
+
revert Error.PresaleStakingDisabled();
|
|
218
207
|
|
|
219
|
-
|
|
208
|
+
core.validateAndConsumeNonce(
|
|
209
|
+
user,
|
|
210
|
+
Hash.hashDataForPresaleStake(isStaking, 1),
|
|
211
|
+
originExecutor,
|
|
212
|
+
nonce,
|
|
213
|
+
true,
|
|
214
|
+
signature
|
|
215
|
+
);
|
|
216
|
+
|
|
217
|
+
if (!userPresaleStaker[user].isAllow)
|
|
218
|
+
revert Error.UserIsNotPresaleStaker();
|
|
219
|
+
|
|
220
|
+
uint256 current = userPresaleStaker[user].stakingAmount;
|
|
220
221
|
|
|
221
|
-
|
|
222
|
+
if (isStaking ? current >= 2 : current == 0)
|
|
223
|
+
revert Error.UserPresaleStakerLimitExceeded();
|
|
222
224
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
+
userPresaleStaker[user].stakingAmount = isStaking
|
|
226
|
+
? current + 1
|
|
227
|
+
: current - 1;
|
|
225
228
|
|
|
226
229
|
stakingBaseProcess(
|
|
227
|
-
AccountMetadata({Address: user, IsAService: false}),
|
|
230
|
+
Structs.AccountMetadata({Address: user, IsAService: false}),
|
|
228
231
|
isStaking,
|
|
229
232
|
1,
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
233
|
+
priorityFeePay,
|
|
234
|
+
noncePay,
|
|
235
|
+
true,
|
|
236
|
+
signaturePay
|
|
234
237
|
);
|
|
235
|
-
|
|
236
|
-
markAsyncNonceAsUsed(user, nonce);
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
/**
|
|
240
|
-
* @notice Internal function to manage presale staking limits and permissions
|
|
241
|
-
* @dev Enforces the 2 staking token limit for presale users and tracks staking amounts
|
|
242
|
-
* @param _isStaking True for staking (increments count), false for unstaking (decrements count)
|
|
243
|
-
* @param _user Address of the presale user
|
|
244
|
-
*/
|
|
245
|
-
function presaleClaims(bool _isStaking, address _user) internal {
|
|
246
|
-
if (allowPublicStaking.flag) {
|
|
247
|
-
revert ErrorsLib.PresaleStakingDisabled();
|
|
248
|
-
} else {
|
|
249
|
-
if (userPresaleStaker[_user].isAllow) {
|
|
250
|
-
if (_isStaking) {
|
|
251
|
-
// staking
|
|
252
|
-
|
|
253
|
-
if (userPresaleStaker[_user].stakingAmount >= 2)
|
|
254
|
-
revert ErrorsLib.UserPresaleStakerLimitExceeded();
|
|
255
|
-
|
|
256
|
-
userPresaleStaker[_user].stakingAmount++;
|
|
257
|
-
} else {
|
|
258
|
-
// unstaking
|
|
259
|
-
|
|
260
|
-
if (userPresaleStaker[_user].stakingAmount == 0)
|
|
261
|
-
revert ErrorsLib.UserPresaleStakerLimitExceeded();
|
|
262
|
-
|
|
263
|
-
userPresaleStaker[_user].stakingAmount--;
|
|
264
|
-
}
|
|
265
|
-
} else {
|
|
266
|
-
revert ErrorsLib.UserIsNotPresaleStaker();
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
238
|
}
|
|
270
239
|
|
|
271
240
|
/**
|
|
272
|
-
* @notice
|
|
273
|
-
* @
|
|
274
|
-
* @param
|
|
275
|
-
* @param
|
|
276
|
-
* @param
|
|
277
|
-
* @param
|
|
278
|
-
* @param
|
|
279
|
-
* @param
|
|
280
|
-
* @param
|
|
281
|
-
* @param priorityFlag_EVVM True for async EVVM transaction, false for sync
|
|
282
|
-
* @param signature_EVVM Signature for the EVVM contract transaction
|
|
241
|
+
* @notice Public staking open to any user when enabled.
|
|
242
|
+
* @param user Participant address.
|
|
243
|
+
* @param isStaking True to stake, false to unstake.
|
|
244
|
+
* @param amountOfStaking Number of tokens.
|
|
245
|
+
* @param nonce Async nonce for signature verification.
|
|
246
|
+
* @param signature Participant's authorization signature.
|
|
247
|
+
* @param priorityFeePay Optional priority fee.
|
|
248
|
+
* @param noncePay Nonce for the Core payment.
|
|
249
|
+
* @param signaturePay Signature for the Core payment.
|
|
283
250
|
*/
|
|
284
251
|
function publicStaking(
|
|
285
252
|
address user,
|
|
286
253
|
bool isStaking,
|
|
287
254
|
uint256 amountOfStaking,
|
|
255
|
+
address originExecutor,
|
|
288
256
|
uint256 nonce,
|
|
289
257
|
bytes memory signature,
|
|
290
|
-
uint256
|
|
291
|
-
uint256
|
|
292
|
-
|
|
293
|
-
bytes memory signature_EVVM
|
|
258
|
+
uint256 priorityFeePay,
|
|
259
|
+
uint256 noncePay,
|
|
260
|
+
bytes memory signaturePay
|
|
294
261
|
) external {
|
|
295
|
-
if (!allowPublicStaking.flag)
|
|
296
|
-
revert();
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
if (
|
|
300
|
-
!SignatureUtils.verifyMessageSignedForStake(
|
|
301
|
-
evvm.getEvvmID(),
|
|
302
|
-
user,
|
|
303
|
-
true,
|
|
304
|
-
isStaking,
|
|
305
|
-
amountOfStaking,
|
|
306
|
-
nonce,
|
|
307
|
-
signature
|
|
308
|
-
)
|
|
309
|
-
) revert ErrorsLib.InvalidSignatureOnStaking();
|
|
262
|
+
if (!allowPublicStaking.flag) revert Error.PublicStakingDisabled();
|
|
310
263
|
|
|
311
|
-
|
|
264
|
+
core.validateAndConsumeNonce(
|
|
265
|
+
user,
|
|
266
|
+
Hash.hashDataForPublicStake(isStaking, amountOfStaking),
|
|
267
|
+
originExecutor,
|
|
268
|
+
nonce,
|
|
269
|
+
true,
|
|
270
|
+
signature
|
|
271
|
+
);
|
|
312
272
|
|
|
313
273
|
stakingBaseProcess(
|
|
314
|
-
AccountMetadata({Address: user, IsAService: false}),
|
|
274
|
+
Structs.AccountMetadata({Address: user, IsAService: false}),
|
|
315
275
|
isStaking,
|
|
316
276
|
amountOfStaking,
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
277
|
+
priorityFeePay,
|
|
278
|
+
noncePay,
|
|
279
|
+
true,
|
|
280
|
+
signaturePay
|
|
321
281
|
);
|
|
322
|
-
|
|
323
|
-
markAsyncNonceAsUsed(user, nonce);
|
|
324
282
|
}
|
|
325
283
|
|
|
326
284
|
/**
|
|
327
|
-
* @notice
|
|
328
|
-
* @dev
|
|
329
|
-
* @param amountOfStaking Amount of staking tokens the service intends to stake
|
|
285
|
+
* @notice Step 1: Prepare service (contract) staking
|
|
286
|
+
* @dev Records pre-staking state for atomic validation
|
|
330
287
|
*
|
|
331
|
-
* Service Staking Process:
|
|
332
|
-
* 1.
|
|
333
|
-
* 2.
|
|
334
|
-
* 3.
|
|
288
|
+
* Service Staking Process (ATOMIC - Same TX):
|
|
289
|
+
* 1. prepareServiceStaking: Record balances
|
|
290
|
+
* 2. Evvm.caPay: Transfer Principal Tokens
|
|
291
|
+
* 3. confirmServiceStaking: Validate and complete
|
|
335
292
|
*
|
|
336
|
-
*
|
|
337
|
-
*
|
|
338
|
-
*
|
|
339
|
-
*
|
|
340
|
-
*
|
|
293
|
+
* CRITICAL WARNING:
|
|
294
|
+
* - All 3 steps MUST occur in single transaction
|
|
295
|
+
* - If incomplete, tokens permanently locked
|
|
296
|
+
* - No recovery mechanism for failed process
|
|
297
|
+
* - Service loses tokens if not atomic
|
|
298
|
+
*
|
|
299
|
+
* Metadata Recorded:
|
|
300
|
+
* - service: msg.sender (contract address)
|
|
301
|
+
* - timestamp: block.timestamp (atomicity check)
|
|
302
|
+
* - amountOfStaking: Requested staking tokens
|
|
303
|
+
* - amountServiceBeforeStaking: Service PT balance
|
|
304
|
+
* - amountStakingBeforeStaking: Staking PT balance
|
|
305
|
+
*
|
|
306
|
+
* Core.sol Payment (Step 2):
|
|
307
|
+
* - Service must call Evvm.caPay after this
|
|
308
|
+
* - Transfer: PRICE_OF_STAKING * amountOfStaking
|
|
309
|
+
* - Recipient: address(this) (Staking contract)
|
|
310
|
+
* - Token: Principal Token from Core.sol
|
|
311
|
+
*
|
|
312
|
+
* Access Control:
|
|
313
|
+
* - onlyCA modifier: Only contracts allowed
|
|
314
|
+
* - Checks code size via assembly
|
|
315
|
+
* - EOAs rejected (size == 0)
|
|
316
|
+
*
|
|
317
|
+
* @param amountOfStaking Number of staking tokens to acquire
|
|
341
318
|
*/
|
|
342
319
|
function prepareServiceStaking(uint256 amountOfStaking) external onlyCA {
|
|
343
|
-
serviceStakingData = ServiceStakingMetadata({
|
|
320
|
+
serviceStakingData = Structs.ServiceStakingMetadata({
|
|
344
321
|
service: msg.sender,
|
|
345
322
|
timestamp: block.timestamp,
|
|
346
323
|
amountOfStaking: amountOfStaking,
|
|
347
|
-
amountServiceBeforeStaking:
|
|
324
|
+
amountServiceBeforeStaking: core.getBalance(
|
|
348
325
|
msg.sender,
|
|
349
|
-
|
|
326
|
+
core.getPrincipalTokenAddress()
|
|
350
327
|
),
|
|
351
|
-
amountStakingBeforeStaking:
|
|
328
|
+
amountStakingBeforeStaking: core.getBalance(
|
|
352
329
|
address(this),
|
|
353
|
-
|
|
330
|
+
core.getPrincipalTokenAddress()
|
|
354
331
|
)
|
|
355
332
|
});
|
|
356
333
|
}
|
|
357
334
|
|
|
358
335
|
/**
|
|
359
|
-
* @notice
|
|
360
|
-
* @dev
|
|
336
|
+
* @notice Step 3: Confirm service staking after payment
|
|
337
|
+
* @dev Validates payment and completes atomic staking
|
|
361
338
|
*
|
|
362
|
-
* Validation
|
|
363
|
-
*
|
|
364
|
-
*
|
|
365
|
-
*
|
|
366
|
-
* - Caller matches the service that initiated the preparation
|
|
339
|
+
* Validation Checks:
|
|
340
|
+
* 1. Timestamp: Must equal prepareServiceStaking tx
|
|
341
|
+
* - Ensures atomicity (same transaction)
|
|
342
|
+
* - serviceStakingData.timestamp == block.timestamp
|
|
367
343
|
*
|
|
368
|
-
*
|
|
369
|
-
*
|
|
344
|
+
* 2. Caller: Must match prepareServiceStaking caller
|
|
345
|
+
* - serviceStakingData.service == msg.sender
|
|
346
|
+
* - Prevents staking hijacking
|
|
347
|
+
*
|
|
348
|
+
* 3. Payment Amount: Validates exact transfer
|
|
349
|
+
* - Service balance decreased by exact amount
|
|
350
|
+
* - Staking balance increased by exact amount
|
|
351
|
+
* - totalStakingRequired = PRICE_OF_STAKING *
|
|
352
|
+
* amountOfStaking
|
|
353
|
+
*
|
|
354
|
+
* Core.sol Integration:
|
|
355
|
+
* - Validates caPay occurred between steps 1 and 3
|
|
356
|
+
* - Checks balance deltas via Evvm.getBalance
|
|
357
|
+
* - Token: core.getPrincipalTokenAddress()
|
|
358
|
+
* - Must be exact amount (no overpayment/underpayment)
|
|
359
|
+
*
|
|
360
|
+
* Completion:
|
|
361
|
+
* - Calls stakingBaseProcess on success
|
|
362
|
+
* - Records history with transaction type 0x01
|
|
363
|
+
* - Updates userHistory with staking event
|
|
364
|
+
* - Service becomes staker (isAddressStaker = true)
|
|
365
|
+
*
|
|
366
|
+
* Error Cases:
|
|
367
|
+
* - ServiceDoesNotStakeInSameTx: timestamp mismatch
|
|
368
|
+
* - AddressMismatch: caller mismatch
|
|
369
|
+
* - ServiceDoesNotFulfillCorrectStakingAmount:
|
|
370
|
+
* payment incorrect
|
|
371
|
+
*
|
|
372
|
+
* Access Control:
|
|
373
|
+
* - onlyCA modifier: Only contracts allowed
|
|
370
374
|
*/
|
|
371
375
|
function confirmServiceStaking() external onlyCA {
|
|
372
376
|
uint256 totalStakingRequired = PRICE_OF_STAKING *
|
|
373
377
|
serviceStakingData.amountOfStaking;
|
|
374
378
|
|
|
375
|
-
uint256 actualServiceBalance = evvm.getBalance(
|
|
376
|
-
msg.sender,
|
|
377
|
-
PRINCIPAL_TOKEN_ADDRESS
|
|
378
|
-
);
|
|
379
|
-
|
|
380
|
-
uint256 actualStakingBalance = evvm.getBalance(
|
|
381
|
-
address(this),
|
|
382
|
-
PRINCIPAL_TOKEN_ADDRESS
|
|
383
|
-
);
|
|
384
|
-
|
|
385
379
|
if (
|
|
386
380
|
serviceStakingData.amountServiceBeforeStaking -
|
|
387
381
|
totalStakingRequired !=
|
|
388
|
-
|
|
382
|
+
core.getBalance(msg.sender, core.getPrincipalTokenAddress()) &&
|
|
389
383
|
serviceStakingData.amountStakingBeforeStaking +
|
|
390
384
|
totalStakingRequired !=
|
|
391
|
-
|
|
385
|
+
core.getBalance(address(this), core.getPrincipalTokenAddress())
|
|
392
386
|
)
|
|
393
|
-
revert
|
|
387
|
+
revert Error.ServiceDoesNotFulfillCorrectStakingAmount(
|
|
394
388
|
totalStakingRequired
|
|
395
389
|
);
|
|
396
390
|
|
|
397
391
|
if (serviceStakingData.timestamp != block.timestamp)
|
|
398
|
-
revert
|
|
392
|
+
revert Error.ServiceDoesNotStakeInSameTx();
|
|
399
393
|
|
|
400
394
|
if (serviceStakingData.service != msg.sender)
|
|
401
|
-
revert
|
|
395
|
+
revert Error.AddressMismatch();
|
|
402
396
|
|
|
403
397
|
stakingBaseProcess(
|
|
404
|
-
AccountMetadata({Address: msg.sender, IsAService: true}),
|
|
398
|
+
Structs.AccountMetadata({Address: msg.sender, IsAService: true}),
|
|
405
399
|
true,
|
|
406
400
|
serviceStakingData.amountOfStaking,
|
|
407
401
|
0,
|
|
@@ -422,7 +416,7 @@ contract Staking is AsyncNonce, StakingStructs {
|
|
|
422
416
|
*/
|
|
423
417
|
function serviceUnstaking(uint256 amountOfStaking) external onlyCA {
|
|
424
418
|
stakingBaseProcess(
|
|
425
|
-
AccountMetadata({Address: msg.sender, IsAService: true}),
|
|
419
|
+
Structs.AccountMetadata({Address: msg.sender, IsAService: true}),
|
|
426
420
|
false,
|
|
427
421
|
amountOfStaking,
|
|
428
422
|
0,
|
|
@@ -440,19 +434,18 @@ contract Staking is AsyncNonce, StakingStructs {
|
|
|
440
434
|
* - IsAService: Boolean indicating if the account is a smart contract (service) account
|
|
441
435
|
* @param isStaking True for staking (requires payment), false for unstaking (provides refund)
|
|
442
436
|
* @param amountOfStaking Amount of staking tokens to stake/unstake
|
|
443
|
-
* @param
|
|
444
|
-
* @param
|
|
445
|
-
* @param
|
|
446
|
-
* @param signature_EVVM Signature for EVVM contract transaction
|
|
437
|
+
* @param priorityFeePay Priority fee for EVVM transaction
|
|
438
|
+
* @param noncePay Nonce for EVVM contract transaction
|
|
439
|
+
* @param signaturePay Signature for EVVM contract transaction
|
|
447
440
|
*/
|
|
448
441
|
function stakingBaseProcess(
|
|
449
|
-
AccountMetadata memory account,
|
|
442
|
+
Structs.AccountMetadata memory account,
|
|
450
443
|
bool isStaking,
|
|
451
444
|
uint256 amountOfStaking,
|
|
452
|
-
uint256
|
|
453
|
-
uint256
|
|
454
|
-
bool
|
|
455
|
-
bytes memory
|
|
445
|
+
uint256 priorityFeePay,
|
|
446
|
+
uint256 noncePay,
|
|
447
|
+
bool isAsyncExecEvvm,
|
|
448
|
+
bytes memory signaturePay
|
|
456
449
|
) internal {
|
|
457
450
|
uint256 auxSMsteBalance;
|
|
458
451
|
|
|
@@ -460,19 +453,19 @@ contract Staking is AsyncNonce, StakingStructs {
|
|
|
460
453
|
if (
|
|
461
454
|
getTimeToUserUnlockStakingTime(account.Address) >
|
|
462
455
|
block.timestamp
|
|
463
|
-
) revert
|
|
456
|
+
) revert Error.AddressMustWaitToStakeAgain();
|
|
464
457
|
|
|
465
458
|
if (!account.IsAService)
|
|
466
459
|
makePay(
|
|
467
460
|
account.Address,
|
|
468
461
|
(PRICE_OF_STAKING * amountOfStaking),
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
462
|
+
priorityFeePay,
|
|
463
|
+
isAsyncExecEvvm,
|
|
464
|
+
noncePay,
|
|
465
|
+
signaturePay
|
|
473
466
|
);
|
|
474
467
|
|
|
475
|
-
|
|
468
|
+
core.pointStaker(account.Address, 0x01);
|
|
476
469
|
|
|
477
470
|
auxSMsteBalance = userHistory[account.Address].length == 0
|
|
478
471
|
? amountOfStaking
|
|
@@ -484,19 +477,19 @@ contract Staking is AsyncNonce, StakingStructs {
|
|
|
484
477
|
if (
|
|
485
478
|
getTimeToUserUnlockFullUnstakingTime(account.Address) >
|
|
486
479
|
block.timestamp
|
|
487
|
-
) revert
|
|
480
|
+
) revert Error.AddressMustWaitToFullUnstake();
|
|
488
481
|
|
|
489
|
-
|
|
482
|
+
core.pointStaker(account.Address, 0x00);
|
|
490
483
|
}
|
|
491
484
|
|
|
492
|
-
if (
|
|
485
|
+
if (priorityFeePay != 0 && !account.IsAService)
|
|
493
486
|
makePay(
|
|
494
487
|
account.Address,
|
|
495
|
-
priorityFee_EVVM,
|
|
496
488
|
0,
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
489
|
+
priorityFeePay,
|
|
490
|
+
isAsyncExecEvvm,
|
|
491
|
+
noncePay,
|
|
492
|
+
signaturePay
|
|
500
493
|
);
|
|
501
494
|
|
|
502
495
|
auxSMsteBalance =
|
|
@@ -506,14 +499,14 @@ contract Staking is AsyncNonce, StakingStructs {
|
|
|
506
499
|
amountOfStaking;
|
|
507
500
|
|
|
508
501
|
makeCaPay(
|
|
509
|
-
|
|
502
|
+
core.getPrincipalTokenAddress(),
|
|
510
503
|
account.Address,
|
|
511
504
|
(PRICE_OF_STAKING * amountOfStaking)
|
|
512
505
|
);
|
|
513
506
|
}
|
|
514
507
|
|
|
515
508
|
userHistory[account.Address].push(
|
|
516
|
-
HistoryMetadata({
|
|
509
|
+
Structs.HistoryMetadata({
|
|
517
510
|
transactionType: isStaking
|
|
518
511
|
? bytes32(uint256(1))
|
|
519
512
|
: bytes32(uint256(2)),
|
|
@@ -523,14 +516,11 @@ contract Staking is AsyncNonce, StakingStructs {
|
|
|
523
516
|
})
|
|
524
517
|
);
|
|
525
518
|
|
|
526
|
-
if (
|
|
527
|
-
evvm.isAddressStaker(msg.sender) &&
|
|
528
|
-
!account.IsAService
|
|
529
|
-
) {
|
|
519
|
+
if (core.isAddressStaker(msg.sender) && !account.IsAService) {
|
|
530
520
|
makeCaPay(
|
|
531
|
-
|
|
521
|
+
core.getPrincipalTokenAddress(),
|
|
532
522
|
msg.sender,
|
|
533
|
-
(
|
|
523
|
+
(core.getRewardAmount() * 2) + priorityFeePay
|
|
534
524
|
);
|
|
535
525
|
}
|
|
536
526
|
}
|
|
@@ -576,11 +566,11 @@ contract Staking is AsyncNonce, StakingStructs {
|
|
|
576
566
|
userHistory[user][idToOverwriteUserHistory]
|
|
577
567
|
.timestamp = timestampToBeOverwritten;
|
|
578
568
|
|
|
579
|
-
if (
|
|
569
|
+
if (core.isAddressStaker(msg.sender)) {
|
|
580
570
|
makeCaPay(
|
|
581
|
-
|
|
571
|
+
core.getPrincipalTokenAddress(),
|
|
582
572
|
msg.sender,
|
|
583
|
-
(
|
|
573
|
+
(core.getRewardAmount() * 1)
|
|
584
574
|
);
|
|
585
575
|
}
|
|
586
576
|
}
|
|
@@ -597,7 +587,7 @@ contract Staking is AsyncNonce, StakingStructs {
|
|
|
597
587
|
* @param user Address of the user making the payment
|
|
598
588
|
* @param amount Amount to be paid in Principal Tokens
|
|
599
589
|
* @param priorityFee Additional priority fee for the transaction
|
|
600
|
-
* @param
|
|
590
|
+
* @param isAsyncExec True for async payment, false for sync payment
|
|
601
591
|
* @param nonce Nonce for the EVVM transaction
|
|
602
592
|
* @param signature Signature authorizing the payment
|
|
603
593
|
*/
|
|
@@ -605,20 +595,20 @@ contract Staking is AsyncNonce, StakingStructs {
|
|
|
605
595
|
address user,
|
|
606
596
|
uint256 amount,
|
|
607
597
|
uint256 priorityFee,
|
|
608
|
-
bool
|
|
598
|
+
bool isAsyncExec,
|
|
609
599
|
uint256 nonce,
|
|
610
600
|
bytes memory signature
|
|
611
601
|
) internal {
|
|
612
|
-
|
|
602
|
+
core.pay(
|
|
613
603
|
user,
|
|
614
604
|
address(this),
|
|
615
605
|
"",
|
|
616
|
-
|
|
606
|
+
core.getPrincipalTokenAddress(),
|
|
617
607
|
amount,
|
|
618
608
|
priorityFee,
|
|
619
|
-
nonce,
|
|
620
|
-
priorityFlag,
|
|
621
609
|
address(this),
|
|
610
|
+
nonce,
|
|
611
|
+
isAsyncExec,
|
|
622
612
|
signature
|
|
623
613
|
);
|
|
624
614
|
}
|
|
@@ -635,7 +625,7 @@ contract Staking is AsyncNonce, StakingStructs {
|
|
|
635
625
|
address user,
|
|
636
626
|
uint256 amount
|
|
637
627
|
) internal {
|
|
638
|
-
|
|
628
|
+
core.caPay(user, tokenAddress, amount);
|
|
639
629
|
}
|
|
640
630
|
|
|
641
631
|
//▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀
|
|
@@ -648,9 +638,9 @@ contract Staking is AsyncNonce, StakingStructs {
|
|
|
648
638
|
* @param _staker Address to be added to the presale staker list
|
|
649
639
|
*/
|
|
650
640
|
function addPresaleStaker(address _staker) external onlyOwner {
|
|
651
|
-
if (presaleStakerCount > LIMIT_PRESALE_STAKER)
|
|
652
|
-
revert();
|
|
653
|
-
|
|
641
|
+
if (presaleStakerCount > LIMIT_PRESALE_STAKER)
|
|
642
|
+
revert Error.LimitPresaleStakersExceeded();
|
|
643
|
+
|
|
654
644
|
userPresaleStaker[_staker].isAllow = true;
|
|
655
645
|
presaleStakerCount++;
|
|
656
646
|
}
|
|
@@ -662,9 +652,9 @@ contract Staking is AsyncNonce, StakingStructs {
|
|
|
662
652
|
*/
|
|
663
653
|
function addPresaleStakers(address[] calldata _stakers) external onlyOwner {
|
|
664
654
|
for (uint256 i = 0; i < _stakers.length; i++) {
|
|
665
|
-
if (presaleStakerCount > LIMIT_PRESALE_STAKER)
|
|
666
|
-
revert();
|
|
667
|
-
|
|
655
|
+
if (presaleStakerCount > LIMIT_PRESALE_STAKER)
|
|
656
|
+
revert Error.LimitPresaleStakersExceeded();
|
|
657
|
+
|
|
668
658
|
userPresaleStaker[_stakers[i]].isAllow = true;
|
|
669
659
|
presaleStakerCount++;
|
|
670
660
|
}
|
|
@@ -694,12 +684,13 @@ contract Staking is AsyncNonce, StakingStructs {
|
|
|
694
684
|
* @dev Can only be called by the proposed admin after the time delay has passed
|
|
695
685
|
*/
|
|
696
686
|
function acceptNewAdmin() external {
|
|
697
|
-
if (
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
687
|
+
if (msg.sender != admin.proposal)
|
|
688
|
+
revert Error.SenderIsNotProposedAdmin();
|
|
689
|
+
|
|
690
|
+
if (admin.timeToAccept > block.timestamp)
|
|
691
|
+
revert Error.TimeToAcceptProposalNotReached();
|
|
692
|
+
|
|
693
|
+
admin.current = admin.proposal;
|
|
703
694
|
admin.proposal = address(0);
|
|
704
695
|
admin.timeToAccept = 0;
|
|
705
696
|
}
|
|
@@ -728,10 +719,10 @@ contract Staking is AsyncNonce, StakingStructs {
|
|
|
728
719
|
* @dev Can only be called by the current admin after the 1-day time delay
|
|
729
720
|
*/
|
|
730
721
|
function acceptNewGoldenFisher() external onlyOwner {
|
|
731
|
-
if (goldenFisher.timeToAccept > block.timestamp)
|
|
732
|
-
revert();
|
|
733
|
-
|
|
734
|
-
goldenFisher.
|
|
722
|
+
if (goldenFisher.timeToAccept > block.timestamp)
|
|
723
|
+
revert Error.TimeToAcceptProposalNotReached();
|
|
724
|
+
|
|
725
|
+
goldenFisher.current = goldenFisher.proposal;
|
|
735
726
|
goldenFisher.proposal = address(0);
|
|
736
727
|
goldenFisher.timeToAccept = 0;
|
|
737
728
|
}
|
|
@@ -764,10 +755,10 @@ contract Staking is AsyncNonce, StakingStructs {
|
|
|
764
755
|
* @dev Can only be called by the current admin after the 1-day time delay
|
|
765
756
|
*/
|
|
766
757
|
function acceptSetSecondsToUnlockStaking() external onlyOwner {
|
|
767
|
-
if (secondsToUnlockStaking.timeToAccept > block.timestamp)
|
|
768
|
-
revert();
|
|
769
|
-
|
|
770
|
-
secondsToUnlockStaking.
|
|
758
|
+
if (secondsToUnlockStaking.timeToAccept > block.timestamp)
|
|
759
|
+
revert Error.TimeToAcceptProposalNotReached();
|
|
760
|
+
|
|
761
|
+
secondsToUnlockStaking.current = secondsToUnlockStaking.proposal;
|
|
771
762
|
secondsToUnlockStaking.proposal = 0;
|
|
772
763
|
secondsToUnlockStaking.timeToAccept = 0;
|
|
773
764
|
}
|
|
@@ -800,10 +791,10 @@ contract Staking is AsyncNonce, StakingStructs {
|
|
|
800
791
|
* @dev Can only be called by the current admin after the 1-day time delay
|
|
801
792
|
*/
|
|
802
793
|
function confirmSetSecondsToUnllockFullUnstaking() external onlyOwner {
|
|
803
|
-
if (secondsToUnllockFullUnstaking.timeToAccept > block.timestamp)
|
|
804
|
-
revert();
|
|
805
|
-
|
|
806
|
-
secondsToUnllockFullUnstaking.
|
|
794
|
+
if (secondsToUnllockFullUnstaking.timeToAccept > block.timestamp)
|
|
795
|
+
revert Error.TimeToAcceptProposalNotReached();
|
|
796
|
+
|
|
797
|
+
secondsToUnllockFullUnstaking.current = secondsToUnllockFullUnstaking
|
|
807
798
|
.proposal;
|
|
808
799
|
secondsToUnllockFullUnstaking.proposal = 0;
|
|
809
800
|
secondsToUnllockFullUnstaking.timeToAccept = 0;
|
|
@@ -832,10 +823,10 @@ contract Staking is AsyncNonce, StakingStructs {
|
|
|
832
823
|
* @dev Toggles between enabled/disabled state for public staking after 1-day delay
|
|
833
824
|
*/
|
|
834
825
|
function confirmChangeAllowPublicStaking() external onlyOwner {
|
|
835
|
-
if (allowPublicStaking.timeToAccept > block.timestamp)
|
|
836
|
-
revert();
|
|
837
|
-
|
|
838
|
-
allowPublicStaking = BoolTypeProposal({
|
|
826
|
+
if (allowPublicStaking.timeToAccept > block.timestamp)
|
|
827
|
+
revert Error.TimeToAcceptProposalNotReached();
|
|
828
|
+
|
|
829
|
+
allowPublicStaking = ProposalStructs.BoolTypeProposal({
|
|
839
830
|
flag: !allowPublicStaking.flag,
|
|
840
831
|
timeToAccept: 0
|
|
841
832
|
});
|
|
@@ -864,13 +855,11 @@ contract Staking is AsyncNonce, StakingStructs {
|
|
|
864
855
|
* @dev Toggles between enabled/disabled state for presale staking after 1-day delay
|
|
865
856
|
*/
|
|
866
857
|
function confirmChangeAllowPresaleStaking() external onlyOwner {
|
|
867
|
-
if (allowPresaleStaking.timeToAccept > block.timestamp)
|
|
868
|
-
revert();
|
|
869
|
-
|
|
870
|
-
allowPresaleStaking =
|
|
871
|
-
|
|
872
|
-
timeToAccept: 0
|
|
873
|
-
});
|
|
858
|
+
if (allowPresaleStaking.timeToAccept > block.timestamp)
|
|
859
|
+
revert Error.TimeToAcceptProposalNotReached();
|
|
860
|
+
|
|
861
|
+
allowPresaleStaking.flag = !allowPresaleStaking.flag;
|
|
862
|
+
allowPresaleStaking.timeToAccept = 0;
|
|
874
863
|
}
|
|
875
864
|
|
|
876
865
|
/**
|
|
@@ -880,7 +869,9 @@ contract Staking is AsyncNonce, StakingStructs {
|
|
|
880
869
|
*/
|
|
881
870
|
function proposeEstimator(address _estimator) external onlyOwner {
|
|
882
871
|
estimatorAddress.proposal = _estimator;
|
|
883
|
-
estimatorAddress.timeToAccept =
|
|
872
|
+
estimatorAddress.timeToAccept =
|
|
873
|
+
block.timestamp +
|
|
874
|
+
TIME_TO_ACCEPT_PROPOSAL;
|
|
884
875
|
}
|
|
885
876
|
|
|
886
877
|
/**
|
|
@@ -897,13 +888,13 @@ contract Staking is AsyncNonce, StakingStructs {
|
|
|
897
888
|
* @dev Can only be called by the current admin after the 1-day time delay
|
|
898
889
|
*/
|
|
899
890
|
function acceptNewEstimator() external onlyOwner {
|
|
900
|
-
if (estimatorAddress.timeToAccept > block.timestamp)
|
|
901
|
-
revert();
|
|
902
|
-
|
|
903
|
-
estimatorAddress.
|
|
891
|
+
if (estimatorAddress.timeToAccept > block.timestamp)
|
|
892
|
+
revert Error.TimeToAcceptProposalNotReached();
|
|
893
|
+
|
|
894
|
+
estimatorAddress.current = estimatorAddress.proposal;
|
|
904
895
|
estimatorAddress.proposal = address(0);
|
|
905
896
|
estimatorAddress.timeToAccept = 0;
|
|
906
|
-
estimator =
|
|
897
|
+
estimator = Estimator(estimatorAddress.current);
|
|
907
898
|
}
|
|
908
899
|
|
|
909
900
|
//▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀▄▀
|
|
@@ -914,11 +905,11 @@ contract Staking is AsyncNonce, StakingStructs {
|
|
|
914
905
|
* @notice Returns the complete staking history for an address
|
|
915
906
|
* @dev Returns an array of all staking transactions and rewards for the user
|
|
916
907
|
* @param _account Address to query the history for
|
|
917
|
-
* @return Array of HistoryMetadata containing all transactions
|
|
908
|
+
* @return Array of Structs.HistoryMetadata containing all transactions
|
|
918
909
|
*/
|
|
919
910
|
function getAddressHistory(
|
|
920
911
|
address _account
|
|
921
|
-
) public view returns (HistoryMetadata[] memory) {
|
|
912
|
+
) public view returns (Structs.HistoryMetadata[] memory) {
|
|
922
913
|
return userHistory[_account];
|
|
923
914
|
}
|
|
924
915
|
|
|
@@ -939,12 +930,12 @@ contract Staking is AsyncNonce, StakingStructs {
|
|
|
939
930
|
* @dev Allows accessing individual transactions by index
|
|
940
931
|
* @param _account Address to query the history for
|
|
941
932
|
* @param _index Index of the transaction to retrieve (0-based)
|
|
942
|
-
* @return HistoryMetadata of the transaction at the specified index
|
|
933
|
+
* @return Structs.HistoryMetadata of the transaction at the specified index
|
|
943
934
|
*/
|
|
944
935
|
function getAddressHistoryByIndex(
|
|
945
936
|
address _account,
|
|
946
937
|
uint256 _index
|
|
947
|
-
) public view returns (HistoryMetadata memory) {
|
|
938
|
+
) public view returns (Structs.HistoryMetadata memory) {
|
|
948
939
|
return userHistory[_account][_index];
|
|
949
940
|
}
|
|
950
941
|
|
|
@@ -970,13 +961,13 @@ contract Staking is AsyncNonce, StakingStructs {
|
|
|
970
961
|
if (userHistory[_account][i - 1].totalStaked == 0) {
|
|
971
962
|
return
|
|
972
963
|
userHistory[_account][i - 1].timestamp +
|
|
973
|
-
secondsToUnllockFullUnstaking.
|
|
964
|
+
secondsToUnllockFullUnstaking.current;
|
|
974
965
|
}
|
|
975
966
|
}
|
|
976
967
|
|
|
977
968
|
return
|
|
978
969
|
userHistory[_account][0].timestamp +
|
|
979
|
-
secondsToUnllockFullUnstaking.
|
|
970
|
+
secondsToUnllockFullUnstaking.current;
|
|
980
971
|
}
|
|
981
972
|
|
|
982
973
|
/**
|
|
@@ -996,7 +987,7 @@ contract Staking is AsyncNonce, StakingStructs {
|
|
|
996
987
|
if (userHistory[_account][lengthOfHistory - 1].totalStaked == 0) {
|
|
997
988
|
return
|
|
998
989
|
userHistory[_account][lengthOfHistory - 1].timestamp +
|
|
999
|
-
secondsToUnlockStaking.
|
|
990
|
+
secondsToUnlockStaking.current;
|
|
1000
991
|
} else {
|
|
1001
992
|
return 0;
|
|
1002
993
|
}
|
|
@@ -1008,7 +999,7 @@ contract Staking is AsyncNonce, StakingStructs {
|
|
|
1008
999
|
* @return Number of seconds required to wait for full unstaking
|
|
1009
1000
|
*/
|
|
1010
1001
|
function getSecondsToUnlockFullUnstaking() external view returns (uint256) {
|
|
1011
|
-
return secondsToUnllockFullUnstaking.
|
|
1002
|
+
return secondsToUnllockFullUnstaking.current;
|
|
1012
1003
|
}
|
|
1013
1004
|
|
|
1014
1005
|
/**
|
|
@@ -1017,7 +1008,7 @@ contract Staking is AsyncNonce, StakingStructs {
|
|
|
1017
1008
|
* @return Number of seconds required to wait between unstaking and staking
|
|
1018
1009
|
*/
|
|
1019
1010
|
function getSecondsToUnlockStaking() external view returns (uint256) {
|
|
1020
|
-
return secondsToUnlockStaking.
|
|
1011
|
+
return secondsToUnlockStaking.current;
|
|
1021
1012
|
}
|
|
1022
1013
|
|
|
1023
1014
|
/**
|
|
@@ -1044,7 +1035,7 @@ contract Staking is AsyncNonce, StakingStructs {
|
|
|
1044
1035
|
* @return Address of the current golden fisher
|
|
1045
1036
|
*/
|
|
1046
1037
|
function getGoldenFisher() external view returns (address) {
|
|
1047
|
-
return goldenFisher.
|
|
1038
|
+
return goldenFisher.current;
|
|
1048
1039
|
}
|
|
1049
1040
|
|
|
1050
1041
|
/**
|
|
@@ -1078,7 +1069,7 @@ contract Staking is AsyncNonce, StakingStructs {
|
|
|
1078
1069
|
* @return Address of the current estimator contract
|
|
1079
1070
|
*/
|
|
1080
1071
|
function getEstimatorAddress() external view returns (address) {
|
|
1081
|
-
return estimatorAddress.
|
|
1072
|
+
return estimatorAddress.current;
|
|
1082
1073
|
}
|
|
1083
1074
|
|
|
1084
1075
|
/**
|
|
@@ -1102,12 +1093,12 @@ contract Staking is AsyncNonce, StakingStructs {
|
|
|
1102
1093
|
/**
|
|
1103
1094
|
* @notice Returns the complete public staking configuration and status
|
|
1104
1095
|
* @dev Includes current flag state and any pending changes with timestamps
|
|
1105
|
-
* @return BoolTypeProposal struct containing flag and timeToAccept
|
|
1096
|
+
* @return ProposalStructs.BoolTypeProposal struct containing flag and timeToAccept
|
|
1106
1097
|
*/
|
|
1107
|
-
function
|
|
1098
|
+
function getAllowPublicStaking()
|
|
1108
1099
|
external
|
|
1109
1100
|
view
|
|
1110
|
-
returns (BoolTypeProposal memory)
|
|
1101
|
+
returns (ProposalStructs.BoolTypeProposal memory)
|
|
1111
1102
|
{
|
|
1112
1103
|
return allowPublicStaking;
|
|
1113
1104
|
}
|
|
@@ -1115,32 +1106,48 @@ contract Staking is AsyncNonce, StakingStructs {
|
|
|
1115
1106
|
/**
|
|
1116
1107
|
* @notice Returns the complete presale staking configuration and status
|
|
1117
1108
|
* @dev Includes current flag state and any pending changes with timestamps
|
|
1118
|
-
* @return BoolTypeProposal struct containing flag and timeToAccept
|
|
1109
|
+
* @return ProposalStructs.BoolTypeProposal struct containing flag and timeToAccept
|
|
1119
1110
|
*/
|
|
1120
1111
|
function getAllowPresaleStaking()
|
|
1121
1112
|
external
|
|
1122
1113
|
view
|
|
1123
|
-
returns (BoolTypeProposal memory)
|
|
1114
|
+
returns (ProposalStructs.BoolTypeProposal memory)
|
|
1124
1115
|
{
|
|
1125
1116
|
return allowPresaleStaking;
|
|
1126
1117
|
}
|
|
1127
1118
|
|
|
1119
|
+
/**
|
|
1120
|
+
* @notice Gets the unique identifier string for this EVVM instance
|
|
1121
|
+
* @dev Returns the EvvmID used for distinguishing different EVVM deployments
|
|
1122
|
+
* @return Unique EvvmID string
|
|
1123
|
+
*/
|
|
1124
|
+
function getEvvmID() external view returns (uint256) {
|
|
1125
|
+
return core.getEvvmID();
|
|
1126
|
+
}
|
|
1127
|
+
|
|
1128
1128
|
/**
|
|
1129
1129
|
* @notice Returns the address of the EVVM core contract
|
|
1130
1130
|
* @dev The EVVM contract handles payments and staker registration
|
|
1131
1131
|
* @return Address of the EVVM core contract
|
|
1132
1132
|
*/
|
|
1133
|
-
function
|
|
1133
|
+
function getCoreAddress() external view returns (address) {
|
|
1134
1134
|
return EVVM_ADDRESS;
|
|
1135
1135
|
}
|
|
1136
1136
|
|
|
1137
|
+
function getIfUsedAsyncNonce(
|
|
1138
|
+
address user,
|
|
1139
|
+
uint256 nonce
|
|
1140
|
+
) external view returns (bool) {
|
|
1141
|
+
return core.getIfUsedAsyncNonce(user, nonce);
|
|
1142
|
+
}
|
|
1143
|
+
|
|
1137
1144
|
/**
|
|
1138
1145
|
* @notice Returns the address representing the Principal Token
|
|
1139
1146
|
* @dev This is a constant address used to represent the principal token
|
|
1140
1147
|
* @return Address representing the Principal Token (0x...0001)
|
|
1141
1148
|
*/
|
|
1142
|
-
function getMateAddress() external
|
|
1143
|
-
return
|
|
1149
|
+
function getMateAddress() external view returns (address) {
|
|
1150
|
+
return core.getPrincipalTokenAddress();
|
|
1144
1151
|
}
|
|
1145
1152
|
|
|
1146
1153
|
/**
|
|
@@ -1149,6 +1156,6 @@ contract Staking is AsyncNonce, StakingStructs {
|
|
|
1149
1156
|
* @return Address of the current contract admin
|
|
1150
1157
|
*/
|
|
1151
1158
|
function getOwner() external view returns (address) {
|
|
1152
|
-
return admin.
|
|
1159
|
+
return admin.current;
|
|
1153
1160
|
}
|
|
1154
1161
|
}
|