diff --git a/contracts/sfc/SFC.sol b/contracts/sfc/SFC.sol index 5a3aa63..66d3d99 100644 --- a/contracts/sfc/SFC.sol +++ b/contracts/sfc/SFC.sol @@ -138,7 +138,7 @@ contract SFC is SFCBase, Version { bytes memory pubkey = getValidatorPubkey[vid]; if (pubkey.length > 0 && pubkeyHashToValidatorID[keccak256(pubkey)] != vid) { if (pubkeyHashToValidatorID[keccak256(pubkey)] != 0) { - revert PubkeyExists(); + revert PubkeyUsedByOtherValidator(); } pubkeyHashToValidatorID[keccak256(pubkey)] = vid; } @@ -154,13 +154,13 @@ contract SFC is SFCBase, Version { revert ValidatorNotExists(); } if (keccak256(pubkey) == keccak256(getValidatorPubkey[validatorID])) { - revert SamePubkey(); + revert PubkeyNotChanged(); } if (pubkeyHashToValidatorID[keccak256(pubkey)] != 0) { - revert PubkeyExists(); + revert PubkeyUsedByOtherValidator(); } if (validatorPubkeyChanges[validatorID] != 0) { - revert PubkeyAllowedOnlyOnce(); + revert TooManyPubkeyUpdates(); } validatorPubkeyChanges[validatorID]++; @@ -187,7 +187,7 @@ contract SFC is SFCBase, Version { revert NotAuthorized(); } if (getRedirection[from] == to) { - revert RequestedCompleted(); + revert AlreadyRedirected(); } if (from == to) { revert SameAddress(); diff --git a/contracts/sfc/SFCBase.sol b/contracts/sfc/SFCBase.sol index 164404f..4c46db0 100644 --- a/contracts/sfc/SFCBase.sol +++ b/contracts/sfc/SFCBase.sol @@ -24,11 +24,11 @@ contract SFCBase is SFCState { error ZeroRewards(); // pubkeys - error PubkeyExists(); + error PubkeyUsedByOtherValidator(); error MalformedPubkey(); - error SamePubkey(); + error PubkeyNotChanged(); error EmptyPubkey(); - error PubkeyAllowedOnlyOnce(); + error TooManyPubkeyUpdates(); // redirections error SameRedirectionAuthorizer(); @@ -42,7 +42,7 @@ contract SFCBase is SFCState { error WrongValidatorStatus(); // requests - error RequestedCompleted(); + error AlreadyRedirected(); error RequestExists(); error RequestNotExists(); diff --git a/contracts/sfc/SFCLib.sol b/contracts/sfc/SFCLib.sol index 47e1f36..debc464 100644 --- a/contracts/sfc/SFCLib.sol +++ b/contracts/sfc/SFCLib.sol @@ -103,7 +103,7 @@ contract SFCLib is SFCBase { revert EmptyPubkey(); } if (pubkeyHashToValidatorID[keccak256(pubkey)] != 0) { - revert PubkeyExists(); + revert PubkeyUsedByOtherValidator(); } _createValidator(msg.sender, pubkey); _delegate(msg.sender, lastValidatorID, msg.value); diff --git a/contracts/sfc/SFCState.sol b/contracts/sfc/SFCState.sol index e19fadd..6a961f0 100644 --- a/contracts/sfc/SFCState.sol +++ b/contracts/sfc/SFCState.sol @@ -14,10 +14,10 @@ contract SFCState is Initializable, Ownable { uint256 status; uint256 deactivatedTime; uint256 deactivatedEpoch; - uint256 receivedStake; + uint256 receivedStake; // from all delegators (weight of the validator) uint256 createdEpoch; uint256 createdTime; - address auth; + address auth; // self-stake delegator } NodeDriverAuth internal node; @@ -28,26 +28,34 @@ contract SFCState is Initializable, Ownable { uint256 unlockedReward; } + // last sealed epoch (currentEpoch - 1) uint256 public currentSealedEpoch; mapping(uint256 => Validator) public getValidator; mapping(address => uint256) public getValidatorID; mapping(uint256 => bytes) public getValidatorPubkey; uint256 public lastValidatorID; + + // total stake of all validators - includes slashed/offline validators uint256 public totalStake; + // total stake of active (OK_STATUS) validators (total weight) uint256 public totalActiveStake; + // sum of penalties subtracted from successful withdrawals - TODO misleading - remove? uint256 public totalSlashedStake; - mapping(address => mapping(uint256 => Rewards)) internal _rewardsStash; // addr, validatorID -> Rewards + // delegator => validator ID => stashed rewards (to be claimed/restaked) + mapping(address => mapping(uint256 => Rewards)) internal _rewardsStash; + // delegator => validator ID => last epoch number for which were rewards stashed mapping(address => mapping(uint256 => uint256)) public stashedRewardsUntilEpoch; struct WithdrawalRequest { - uint256 epoch; - uint256 time; + uint256 epoch; // epoch where undelegated + uint256 time; // when undelegated uint256 amount; } + // delegator => validator ID => withdrawal ID => withdrawal request mapping(address => mapping(uint256 => mapping(uint256 => WithdrawalRequest))) public getWithdrawalRequest; struct LockedDelegation { @@ -57,43 +65,56 @@ contract SFCState is Initializable, Ownable { uint256 duration; } + // delegator => validator ID => current stake (locked+unlocked) mapping(address => mapping(uint256 => uint256)) public getStake; + // delegator => validator ID => locked stake info mapping(address => mapping(uint256 => LockedDelegation)) public getLockupInfo; mapping(address => mapping(uint256 => Rewards)) public getStashedLockupRewards; struct EpochSnapshot { + // validator ID => validator weight in the epoch mapping(uint256 => uint256) receivedStake; + // validator ID => accumulated ( delegatorsReward * 1e18 / receivedStake ) mapping(uint256 => uint256) accumulatedRewardPerToken; + // validator ID => accumulated online time mapping(uint256 => uint256) accumulatedUptime; + // validator ID => gas fees from txs originated by the validator mapping(uint256 => uint256) accumulatedOriginatedTxsFee; mapping(uint256 => uint256) offlineTime; mapping(uint256 => uint256) offlineBlocks; uint256[] validatorIDs; uint256 endTime; uint256 endBlock; - uint256 epochFee; - uint256 totalBaseRewardWeight; - uint256 totalTxRewardWeight; - uint256 baseRewardPerSecond; - uint256 totalStake; - uint256 totalSupply; + uint256 epochFee; // gas fees from txs in the epoch + uint256 totalBaseRewardWeight; // sum( stake * uptimeRatio ^ 2 ) TODO write only - remove? + uint256 totalTxRewardWeight; // sum( originatedTxsFee * uptimeRatio ) TODO write only - remove? + uint256 baseRewardPerSecond; // the base reward to divide among validators for each second of the epoch + uint256 totalStake; // total weight of all validators + uint256 totalSupply; // total supply of native tokens } + // the total supply of native tokens in the chain uint256 public totalSupply; + // epoch id => epoch snapshot mapping(uint256 => EpochSnapshot) public getEpochSnapshot; - mapping(uint256 => uint256) public slashingRefundRatio; // validator ID -> (slashing refund ratio) + // validator ID -> slashing refund ratio (allows to withdraw slashed stake) + mapping(uint256 => uint256) public slashingRefundRatio; + // the minimal gas price calculated for the current epoch uint256 public minGasPrice; + // the treasure contract (receives unlock penalties and a part of epoch fees) address public treasuryAddress; + // the SFCLib contract address internal libAddress; ConstantsManager internal c; + // the governance contract (to recalculate votes when a stake changes) address public voteBookAddress; struct Penalty { @@ -103,13 +124,18 @@ contract SFCState is Initializable, Ownable { // delegator => validatorID => penalties info mapping(address => mapping(uint256 => Penalty[])) public getStashedPenalties; + // validator ID => amount of pubkey updates mapping(uint256 => uint256) internal validatorPubkeyChanges; + // keccak256(pubkey bytes) => validator ID (prevents using the same key by multiple validators) mapping(bytes32 => uint256) internal pubkeyHashToValidatorID; + // address authorized to initiate redirection address public redirectionAuthorizer; + // delegator => withdrawals/claims receiver mapping(address => address) public getRedirectionRequest; + // delegator => withdrawals/claims receiver mapping(address => address) public getRedirection; }