# SKALE Manager Specification :::warning For **ConsenSys Diligence** only, not for public distribution ::: > Code lock: 24JAN2020 > Branch: feature/SKALE-1642-delegation > Commit: `50c8f4e037f6bf578d62bd752516b17237b55811` ## Table of Contents [TOC] ## Introduction This specification defines the implementation requirements for SKALE Manager, including interfaces to the external-facing components of the SKALE Network and how they are intended to be used. SKALE Network is based on open sourced technologies developed by N.O.D.E. Foundation and SKALE Labs, with specific technologies (skaled) forked and modified from Ethereum (Aleth client). ## Overall Description The SKALE Manager orchestrates and administers the entirety of the SKALE Network with respect to business, engineering, and security operations. The Manager is comprised as a set of Solidity contracts and is built to be deployed on the Ethereum mainnet. The Manager system is organized for upgradability by separating data and functional contract functionality. Once QA and security testing is completed, the Manager will be deployed to the Ethereum Mainnet. Before Mainnet release, the SKALE Manager system will have been tested by QA on private Geth testnets, and public Ethereum testnets. SKALE Manager is the interface between dApp developers, validators, delegators, token sale managers, and the N.O.D.E. Foundation. * dApp developers interact with the manager to request and operate SKALE chains in the SKALE network. * Validators interact with the manager to register nodes to the network, accept or reject delegation requests, submit monitoring reports (SLAs), incur slashing should SLAs be faulted, and to receive bounties dependent on monitoring performance metrics. * The N.O.D.E. Foundation interacts with the SKALE Manager to conduct changes and upgrades at the request of a multi-member council. ## Documentation * _this document_ (current) * [SKALE Network whitepaper](https://skale.network/whitepaper) (slightly outdated) ## General Architecture * Constants * Contains common parameters for SKALE Network. * Contract Manager * Main contract to orchestrate upgrades. * Delegation * Contracts to manage delegation, token sale, bounty distribution, and validator functions. * Lockable ERC-777 * ERC-777 token with locked function to provide required token sale functionality. * Groups * Facilitates groups for schains (node group which participate in a particular SKALE chain) and monitor (node group which are monitored by a particular node). * Monitors * Functions and data to monitor other nodes and send monthly reports. * Nodes * Functions and data to manage a node. * Schains * Functions and data to manager a SKALE chain. * SKALE Manager * Manage bounty, NMS verdicts, accept deposit for SKALE chains, and create/delete nodes. * SKALE Token * Lockable ERC-777 with minting, and other functions. * SKALE DKG and Verifier * Cryptographic functions to orchestrate distributed key generation, Elliptic Curve Diffie-Hellman, and verify BLS signatures. ## Files in scope for Security Audit * ContractManager.sol * Permissions.sol * SkaleToken.sol * interfaces/ISkaleToken.sol * interfaces/delegation/IDelegatableToken.sol * interfaces/delegation/IHolderDelegation.sol * interfaces/delegation/IValidatorDelegation.sol * interfaces/tokenSale/ITokenSaleManager.sol * ERC777/LockableERC777.sol * thirdparty/BokkyPooBahsDateTimeLibrary.sol * delegation/DelegationController.sol * delegation/DelegationPeriodManager.sol * delegation/DelegationRequestManager.sol * delegation/DelegationService.sol * delegation/Distributor.sol * delegation/SkaleBalances.sol * delegation/TimeHelpers.sol * delegation/TokenSaleManager.sol * delegation/TokenState.sol * delegation/ValidatorService.sol ## Epochs and timings The SKALE Network conducts bounty payments to SkaleBalances.sol after the node epoch ends, which is after 30 days from the start of node operation with the SKALE Network. ## Third Party Code ### BokkyPooBah's DateTime Library v1.01 * https://github.com/bokkypoobah/BokkyPooBahsDateTimeLibrary ### OpenZeppelin * @openzeppelin/contracts/introspection/IERC1820Registry.sol * @openzeppelin/contracts/math/SafeMath.sol * @openzeppelin/contracts/ownership/Ownable.sol * @openzeppelin/contracts/token/ERC20/IERC20.sol * @openzeppelin/contracts/token/ERC777/IERC777.sol * @openzeppelin/contracts/token/ERC777/IERC777Recipient.sol * @openzeppelin/contracts/token/ERC777/IERC777Sender.sol * @openzeppelin/contracts/utils/Address.sol ## Upgrades SKALE Manager separates contracts into data and functions contacts to facilitate upgradability. ### Planned upgrades - Provide method for re-delegating (and re-bonding) bounty rewards. - Provide method for re-funding and re-starting an expired SKALE chain. - ==TODO: add others== ## Privileged Roles ### Upgrade key The upgrade key to ContractManager can upgrade all contracts. This key will be stored in a physically secure location in a safebox. A designated company Crypto Officer will have access to this safebox room. A request for the Crypto Officer to access the safebox room must be approved by a VP or higher, and N.O.D.E. Foundation representative. The key will be used in the same room where it is stored, and the key will never be removed from this physically secure location. As the N.O.D.E. Foundation matures, we plan to change the owner to a smart contract containing multi-signature functionality or other secure upgrade process. ### Validator Whitelist The N.O.D.E. Foundation will curate a whitelist of trusted validators who will be the only ones able to run mainnet nodes for the launch. Subsequent mainnet launches will incorporate new validators who pass certification and/or participate in testnet activities. Only those validators who match the trusted validator list will be able to accept delegations and create nodes. ### Slashing Enforcement Slashed funds will be held in an escrow account for the first year. A committee of validators will investigate whether the slashing event was due to network error or malicious action. This committee will ultimately decide whether to return the slashed funds or to burn or repurpose funds to a community pool. :::danger **The following section is not for public distribution** ## Token Launch SKALE Network and ConsenSys plan to conduct a token launch of SKALE tokens in Q1'2020. To execute a compliant token launch, token launch participants must prove use of SKALE tokens prior to being able to transfer tokens outside of the network. ### Proof-of-use Token launch participants must not be allowed to transfer their tokens until they: * complete the delegation period for at least 3 months, and * delegate at least 50% of their token launch receipts. ::: :::info Token launch participants are subject to additional Proof-of-use constraints. Other token holders are not subject to this and may delegate and exchange tokens at will. ::: ## General Process Descriptions ### Validation :::info For supporting the initial network launch, SKALE Network will only allow whitelisted validators to register and participate. After network stability, SKALE Network will allow anyone to register. ::: * Validator registers their name, validator Address (msg.sender), description, fee rate, and minimum delegation amount. * If validator registers a new name from the same address, it should throw an error. * Validator can bond (self-delegate) by delegating to their own validator address. * Everyone can view all delegation requests. * Only the validator receiving delegation requests can accept its pending delegation requests. Otherwise requests can be canceled only by request sender (token holder). * Validators can create $$ N $$ nodes if and only if they have sufficient delegations such that $$ total\_delegations >= N * MSR $$ ### Delegation * Token owner submits a delegation request through DelegationService, specifying delegation value, delegation period, and validator ID. * Delegation requests are always for the next epoch (month). * Validator recipient approves the request, and the token is delegated but stays in token holder's wallet. * A token value fraction is marked as delegated to a validator. * Delegated tokens cannot be spent by the token holder, at any time. * Once delegated, the delegated tokens are undelegatable until the delegation period expires. * During delegation, only undelegated and unlocked part of the token can be transferred. * If the delegation period elapses without a undelegate request, the delegation will automatically re-delegate to the same validator for an additional 3 months. * Delegation periods are currently set for 3, 6, and 12 months; and periods are upgradable. * `stakeMultipliers` defines the relative yield of bounties per period. :::info If the delegator is a token launch participant, proof-of-use constraints apply. ::: ### SAFT Investors :::warning *not yet implemented* * SAFT investors may onboard using ConsenSys or directly through SKALE. * SAFT investors will receive tokens to their specified wallet address, just like other token holders. * Lock-up and vesting schedules for each investor address are mapped in the token contract as `lockupEndDate`. * Locked or unvested tokens may not be transferred until they are unlocked. * Locked or unvested tokens may be delegated. * Bounties earned are locked for the **FIRST** 3 months, just as other token holders. ::: ### Bounties * Bounties are calculated and distributed at the end of every month. * All bounties are locked for **first** 3 months starting from token launch date (token launch requirement). ### Slashing :::info For supporting the initial network launch, SKALE Network will operate without slashing. After the network achieves stability, SKALE Network will enforce slashing according to an upgradable table of penalties. ::: * Should a slashing condition occur, the validator's stake is slashed according to the penalties table. * Slashed tokens are locked in the holder's wallet. * The locked tokens can then be locked forever if deemed malicious, or unlocked if the behavior is deemed a mistake. ### Token Launch * ConsenSys will be the distributor of a pre-defined maximum amount of tokens. * At the end of the token launch, only ConsenSys can call token approval function (can be called multiple times) * `approve(address[] walletAddress, uint[] value) allocates values for walletAddresses` * The number of walletAddress must match the number of values. * The total cumulative value to approve must be less than or equal to the balance approved to ConsenSys (seller). * Each approved token launch participant can call retrieve(), to transfer the entire value to walletAddress. * After the transfer the token in walletAddress is locked. User will be able to view the token in Metamask. * Token sale participant then proceeds to delegate token [See Delegation Process](#Delegation). :::info **Note:** * sum of delegation values need to be less or equal the total wallet amount. * The sum of delegation values needs to be at least 50% of the total wallet amount. * The amount that is not delegated is locked, until proof-of-use is verified. ::: ## Validator Service ### registerValidator(string name, address validatorAddress, string description, uint feeRate, uint minimumDelegationAmount) * Executed by a validator, * returns validatorID, and * sets * validatorAddress to the address of the caller, * description provided by validator, * commission/fee rate, and * minimum delegation amount. ### bool unregisterValidator(validatorID) :::info not yet implemented ::: * Unregisters validator, * returns false if the validator did not exist, and * requires zero delegation and bond ### getBondAmount(validatorID) :::info not yet implemented ::: * Returns bond amount deposited by this validator. ### getValidatorInfo(validatorID) :::info not yet implemented ::: * Returns a struct {validatorName, validatorAddress, validatorDescription, feeRate, registrationTime} ### getValidators :::info not yet implemented, will merge soon ::: ### setValidatorName(name) :::info not yet implemented ::: * Sets validator name. ### setValidatorAddress(address newValidatorAddress, uint validatorId) :::info not yet implemented ::: * Sets validator address. * Only executed by the original validator ### setValidatorDescription(string description) :::info not yet implemented ::: * Sets validator description ## Delegation Management ### uint delegate(validatorID, value, delegationPeriod, string description) * Executed by delegator wallet, returns request ID. * Value needs to be less that total yet undelegated token value. :::info * If delegation is accepted, request ID becomes delegation ID. * Delegation requests expire after one week. ::: ### undelegate(delegationID) * Only executable by token holder. * This will succeed only if and only if delegation period passed. * Request will succeed only **before** the delegation period end. * And if you send request before delegation period ends, then tokens will be unlocked only after the period ends. ### cancelPendingDelegation(requestID) * Removes delegation request for this delegator wallet ### uint[] getAllDelegationRequests(); * Get all delegation request ids ### uint[] getRequestsForValidator(validatorID); * Returns an array of pending delegation request IDs for this validator. ### getRequestInfo(requestID) * Returns struct {delegatorAddress, amount, validatorID, delegationPeriod, description, isApproved} ### approveDelegationRequest(requestID); // executed by validator * Approves delegation request and creates a delegation. requestID becomes delegationID ### withdrawBounty(bountyCollectionAddress, amount) * Withdraws bounty from `msg.sender` to particular bounty collection address, * Bounties for token launch participants and validators must be locked for 3 months from start of validation or delegation. :::warning Lock requirement for proof-of-use and prevention of liquidity pools ::: ### getEarnedBountyAmount() * Get earned bounty for `msg.sender`. ### getDelegationOf() * Get an array of delegations for this wallet, each delegation is a struct {delegationID, startMonth, delegationPeriod, value} ### lock(address wallet, uint amount) * Only callable by TokenSaleManager.sol * Makes tokens of target account unavailable to move. :::warning requirement for proof-of-use ::: ## Token State Management There are five (5) token states: * PROPOSED * ACCEPTED * DELEGATED * ENDING_DELEGATED * COMPLETED ### getLockedCount(address holder) * Returns the number of locked tokens for a given address. ### getDelegatedCount(address holder) * Returns the number of delegations for a given address. * ### sold(address holder, uint amount) * Only executed by DelegationService.sol * Increments the cumulative purchased of an address by the given amount. ### accept(uint delegationId) * Only executed by DelegationRequestManager.sol * Sets the state of delegationID to accepted. * Rejects if the delegationID state is not proposed. ### requestUndelegation(uint delegationId) * Only executed by DelegationService.sol * Sets the state of delegationID to ENDING_DELEGATED. * Rejects if the delegationID state is not delegated. ### cancel(uint delegationId) * Only executed by DelegationRequestManager.sol * Rejects if the delegationID state is not PROPOSED. * Delegation proposal is canceled and tokens are available to transfer (if unlocked) otherwise they are available to delegate again. ### slash(uint delegationId, uint amount) * Only executed by DelegationService.sol * Slashes delegated tokens by the slashing amount. * If slashing amount exceeds delegation amount, then total delegation is slashed. * Slashed tokens are locked and held in the holder's wallet. * Slashed tokens may be unlocked if the behavior is deemed a mistake. ### forgive(address wallet, uint amount) * Only executed by DelegationService.sol * Returns specific amount from slashed wallet to given wallet address. ### getSlashedAmount(address holder) * Returns the amount slashed for a given address. ### getState(uint delegationId) ### getPurchasedAmount(address holder) ### isDelegated(State state) ### setState(uint delegationId, State newState) ### initProposed(uint delegationId) ### isLocked(State state) ### proposedToUnlocked(uint delegationId) ### acceptedToDelegated(uint delegationId) ### purchasedProposedToPurchased(uint delegationId, DelegationController.Delegation memory delegation) ### endingDelegatedToUnlocked(uint delegationId, DelegationController.Delegation memory delegation) ### purchasedToUnlocked(address holder) ### _cancel(uint delegationId, DelegationController.Delegation memory delegation) ### getSlashedAmount(address holder) ## Delegation Request Manager √ ### createRequest(address holder, uint validatorId, uint amount, uint delegationPeriod, string info) * Called only by DelegationService.sol * Delegator must have sufficient undelegated tokens to delegate the particular requested amount. * Requested delegation amount must be equal to or greater than the validator's minimum delgation amount. * Delegation request must be made to an existing validatorId. * The delegation request must be made in the appropriate period. ### cancelRequest(uint delegationId, address holderAddress) * Called only by DelegationService.sol. * Only the token holder may cancel pending delegation request. * After request is canceled, token state is COMPLETED. ### acceptRequest(uint delegationId, address validatorAddress) * Called only by DelegationService.sol. * Only the validator receiving the delegation request may accept the request. * After request is accepted, token state is ACCEPTED. ## Delegation Period Manager √ ### isDelegationPeriodAllowed(uint monthsCount) * Returns whether the delegation period is allowed ### setDelegationPeriod(uint monthsCount, uint stakeMultiplier) * Sets a new delegation period and stake multiplier. * Only executed by upgrade key owner. ### removeDelegationPeriod(uint monthsCount) * Removes a delegation period. * Delegations for the removed period that are in-process are completed and paid expected bounty, but any new delegations for the removed period are rejected. * Only executed by upgrade key owner. ## TokenSaleManager TokenSaleManager contract will initially hold all tokens for the sale and allow users to retrieve them. ### approve(address[] walletAddress, uint value) * Allocates values for `walletAddresses` * Only executable by TokenSaleManager owner (ConsenSys) * Retrieve