Bluwhale Protocol Service

Bluwhale Protocol Service

  • Utilizes a proxy contract.

  • Manages system parameters separately through the Settings contract.

  • Does not store funds; all funds are managed by the Vault contract. This contract only has operational authority for fixed roles.

  • Inherits from AccessControlUpgradeable and VRFConsumerBaseV2 (for generating random numbers using Chainlink).

  • Implements the main logic of the Bluwhale protocol.

Core Function Explanations

Trusted Execution Environment (TEE)

Verifier Node

Attestation

Delegation

Rewards

Function Definitions & Explanations

Copy

// SPDX-License-Identifier: GPL-3.0

pragma solidity ^0.8.20;

interface IProtocolService {

/**

* @notice This enum represents result of an attestation reported by verifier

*

* `Valid`: This attestation can be parsed successfully and is not malicious

* `Invalid`: This attestation cannot be parsed successfully

* `Malicious`: This attestation can be parsed successfully but is malicious

*/

enum AttestationResult {

Valid,

Invalid,

Malicious

}

/**

* @notice This struct represents information of a node

*

* `id`: The globally unique ID of the node. The node is automatically registered when

* it calls `nodeEnter` for the first time. Up to 65535 nodes can be registered.

* `listIndex`: The position of the node in the current `activeVrfNodeList`

* `active`: Is the node active?

* `lastConfirmDate`: The date on which reward was last confirmed.

* `missedVerifyCount`: The number of verifications the node currently misses

* `selfTotalRewards`: The total rewards of the node itself

* `selfClaimedRewards`: The rewards claimed by the node itself

* `delegationRewards`: The rewards of the node’s delegator

* `lastEnterTime`: The time when the node last called `nodeEnter` to go online

* `commissionRate`: rate of commission, which is given by NFT holders to the verifier node.(decimals: 4)

* `commissionRateLastModifyAt`: timestamp of last modifying commission rate

*/

struct NodeInfo {

uint16 id;

uint16 listIndex;

bool active;

uint32 lastConfirmDate;

uint64 missedVerifyCount;

int256 selfTotalRewards;

uint256 selfClaimedRewards;

uint256 delegationRewards;

uint256 lastEnterTime;

address claimer;

uint32 commissionRate; // decimals: 4

uint256 commissionRateLastModifyAt;

}

/**

* @notice This struct represents reward information of a BluwhaleNft token

*

* `initialRewards`: When this tokenID is delegated to a node, the initial amount of delegator's rewards needs to be recorded.

* `totalRewards`: The amount of rewards this tokenID has been confirmed

* `claimedRewards`: The amount of rewards this tokenID has been claimed

*/

struct TokenRewardInfo {

uint256 initialRewards;

uint256 totalRewards;

uint256 claimedRewards;

}

/**

* @notice This struct represents staking information of a tee

*

* `valid`: Whether tee is currently valid, invalid tee cannot report attestation

* `staked`: tee’s current staked amount

* `lastReportAt`: The time when tee last reported attestation, used for unstake check

*/

struct TeeStakeInfo {

bool valid;

uint256 staked;

uint256 lastReportAt;

}

/**

* @notice This struct represents information of an attestation

*

* `reporter`: The address of the tee who reported this attestation

* `valid`: The number of votes that this attestation is considered valid (voted by the verifier node)

* `invalid`: The number of votes that this attestation is considered invalid (voted by the verifier node)

* `vrfChosenID`: ID of the currently randomly selected verification nodes

* `slashed`: Has this attestation been slashed?

* `deadline`: Deadline for collecting verification

*/

struct Attestation {

address reporter;

uint16 valid;

uint16 invalid;

uint16 malicious;

uint32 vrfChosenID;

bool slashed;

uint256 deadline;

}

/**

* @notice This struct represents information of an verification with signature

*

* `result`: result of this attestation

* `index`: index of this node in activeVrfNodeList

* `signer`: address of this node (sign the Data to call contract gasless)

* `v`: v of signature signed by signer

* `r`: r of signature signed by signer

* `s`: s of signature signed by signer

*/

struct VerificationInfo {

AttestationResult result;

uint16 index;

address signer;

uint8 v;

bytes32 r;

bytes32 s;

}

// admin

event UpdateVrfAddress(address vrf);

event UpdateSettingsAddress(address settings);

// tee

event TeeStake(address tee, uint256 amount);

event TeeUnstake(address tee, uint256 amount);

event TeeSlash(address tee, bytes32 attestationID, uint256 amount);

event ClaimMaliciousTeeRewards(address verifer, uint256 amount);

event TeeReportAttestations(address tee, bytes32[] attestationIDs, string[] attestationInfos, uint256 requestID);

event ConfirmVrfNodes(uint256 requestId, uint16[] vrfChosen, uint256 deadline);

// node

event NodeRegister(address node, uint16 id);

event NodeActivate(address node);

event NodeClear(address node);

event NodeSlash(address node, bytes32 attestationID, uint256 rewards);

event NodeModifyCommissionRate(address node, uint32 commissionRate);

event NodeSetClaimer(address node, address claimer);

event NodeClaim(address node, address claimer, uint256 rewards);

event NodeReportVerification(address node, bytes32 attestationID, AttestationResult result);

event NodeReportVerificationBatch(bytes32 attestationID, VerificationInfo[] infos);

// delegation

event Delegate(uint256 tokenID, address to);

event Redelegate(uint256 tokenID, address to);

event Undelegate(uint256 tokenID, address to);

event ClaimRewards(uint256 tokenID, uint256 rewards);

/*----------------------------------------------------------------------------------------------------------------*/

/**

* @notice update address of Settings contract.

*

* @dev Only admin role.

* @dev Emits `UpdateSettingsAddress`.

*

* @param settings_: address of Settings contract.

*/

function updateSettingsAddress(address settings_) external;

/**

* @notice update address of BluwhaleVrf contract.

*

* @dev Only admin role.

* @dev Emits `UpdateVrfAddress`.

*

* @param BluwhaleVrf_: address of BluwhaleVrf contract.

*/

function updateVrfAddress(address BluwhaleVrf_) external;

/**

* @notice Tee needs to stake Bluwhales before reporting attestation,

* @notice and Bluwhales will be converted to veBluwhales stored in Vault.

* @notice which will be used to slash when tee proven to be evil.

*

* @dev Only tee role (granted by admin role).

* @dev Emits `TeeStake`.

*

* @param amount: amount of Bluwhale tee plans to stake.

*/

function teeStake(uint256 amount) external;

/**

* @notice Tee withdraws staked veBluwhales, rules are as follows:

* @notice 1. enough time has passed since the last attestation was submitted.

* @notice 2. veBluwhales that have been slashed cannot be unstaked.

* @notice 3. unable to continue reporting attestation after unstaking.

*

* @dev Only tee role (granted by admin role).

* @dev Emits `TeeUnstake`.

*/

function teeUnstake() external;

/**

* @notice When the attestation reported by a tee is proven to be malicious,

* @notice anyone can initiate a teeSlash, which will slash the veBluwhales staked by the tee.

* @notice Each malicious attestation can only be slashed once.

* @notice When the veBluwhales staked by a tee are slashed below a threshold,

* @notice the tee will be forcibly restricted from continuing to report attestation.

*

* @dev Emits `TeeSlash`.

*

* @param attestationID: id of attestation which is proven malicious.

*/

function teeSlash(bytes32 attestationID) external;

/**

* @notice When an attestation reported by a tee is slashed,

* @notice verifiers that have reported verification for this attestation can claim the reward.

* @notice If a verifier have not reported verification of this attestation, it cannot claim the reward.

*

* @dev Emits `ClaimMaliciousTeeRewards`.

*

* @param attestationID: id of attestation which is slashed.

*/

function claimMaliciousTeeRewards(bytes32 attestationID) external;

/**

* @notice Tee reports attestations. The same attestation can only be reported once.

*

* @dev Only staked tee role.

* @dev Emits `TeeReportAttestations`.

* @dev A request to apply for VRF will be sent to chainlink.

* @dev After receiving the callback from chainlink, emits `ConfirmVrfNodes`.

*

* @param attestationInfos: attestations to be reported.

*/

function teeReportAttestations(string[] memory attestationInfos) external;

/**

* @notice In order to save costs more efficiently when selecting nodes in VRF,

* @notice we designed a data structure `activeVrfNodeList` for this purpose.

* @notice `activeVrfNodeList` stores up to 2000 active nodes with delegation weight,

* @notice and each time VRF will select from these nodes.

*

* @notice Nodes need to activate themselves by calling nodeEnter of the smart contract

* @notice To successfully activate a node, caller need to meet the following conditions:

* @notice 1. The caller needs to hold BluwhaleNft, or be delegated by other holders

* @notice 2. If the current `activeVrfNodeList` is full, you need to choose a node

* @notice in the list with less delegation weight than yourself to replace it.

*

* @dev Emits `NodeActivate`.

* @dev If any node is kicked and replaced by your node. Emits `NodeClear`.

* @dev If any node calls nodeEnter for the first time. Emits `NodeRegister`.

*

* @param replacedNode: address of the node that needs to be replaced by your node

* only works when the `activeVrfNodeList` is full

*/

function nodeEnter(address replacedNode) external;

/**

* @notice Exits by node itself, and verification cannot be reported after exiting.

* @notice When a node exits, it will be punished based on missing counts during the online period.

*

* @dev Emits `NodeClear`.

*/

function nodeExit() external;

/**

* @notice Modify the commission rate of verifier node

*

* @dev Emits `NodeModifyCommissionRate`.

*

* @param commissionRate: rate of commission, which is given by NFT holders to the verifier node

*/

function nodeModifyCommissionRate(uint32 commissionRate) external;

/**

* @notice Similar to `nodeEnter`,

* @notice but the txn can be broadcast to the chain by other address after being authenticated by the node.

* @notice Compared with the `nodeEnter`, it is gasless for the verifier node.

* @notice following the eip-712.

*

* @dev Emits `NodeActivate`.

* @dev If any node is kicked and replaced by your node. Emits `NodeClear`.

* @dev If any node calls nodeEnter for the first time. Emits `NodeRegister`.

*

* @param replacedNode: address of the node that needs to be replaced by your node

* only works when the `activeVrfNodeList` is full

* @param expiredAt: transaction expiration time

* @param signer: address of verifier node ready to enter

*/

function nodeEnterWithSignature(

address replacedNode, uint256 expiredAt, address signer, uint8 v, bytes32 r, bytes32 s

) external;

/**

* @notice Similar to `nodeExit`,

* @notice but the txn can be broadcast to the chain by other address after being authenticated by the node.

* @notice Compared with the `nodeExit`, it is gasless for the verifier node.

* @notice following the eip-712.

*

* @dev Emits `NodeClear`.

*

* @param expiredAt: transaction expiration time

* @param signer: address of verifier node ready to exit

*/

function nodeExitWithSignature(

uint256 expiredAt, address signer, uint8 v, bytes32 r, bytes32 s

) external;

/**

* @notice Similar to `nodeModifyCommissionRate`,

* @notice but the txn can be broadcast to the chain by other address after being authenticated by the node.

* @notice Compared with the `nodeModifyCommissionRate`, it is gasless for the verifier node.

* @notice following the eip-712.

*

* @dev Emits `NodeModifyCommissionRate`.

*

* @param commissionRate: rate of commission, which is given by NFT holders to the verifier node

* @param expiredAt: transaction expiration time

* @param signer: address of verifier node

*/

function nodeModifyCommissionRateWithSignature(

uint32 commissionRate, uint256 expiredAt, address signer, uint8 v, bytes32 r, bytes32 s

) external;

/**

* @notice Specify the address that can claim rewards of this verifier node

* @notice it is gasless for the verifier node.

* @notice following the eip-712.

*

* @dev Emits `NodeSetClaimer`.

*

* @param claimer: address of whom can claim reward of this verifier

* @param expiredAt: transaction expiration time

* @param signer: address of verifier node

*/

function nodeSetRewardClaimerWithSignature(

address claimer, uint256 expiredAt, address signer, uint8 v, bytes32 r, bytes32 s

) external;

/**

* @notice Claim reward of node.

* @notice The reward for reporting verifications is divided into two parts: node's reward and delegators' reward

* @notice Only when the node is online for more than 6 hours/day will there be reward.

*

* @dev Emits `NodeClaim`.

*

* @param node: address of node to claim reward

*/

function nodeClaim(address node) external;

/**

* @notice Anyone can initiate a slash for a miss reporting of a node.

* @notice Each miss reporting of a node can only be slashed once.

* @notice When a node is selected by VRF but fails to report a verification within the specified time,

* @notice the node can be slashed.

*

* @dev Emits `NodeSlash`.

*

* @param node: address of node to be slashed

* @param attestationID: id of attestation that node miss reporting

* @param index: index of this node in vrfChosen list of this attestation

*/

function nodeSlash(address node, bytes32 attestationID, uint16 index) external;

/**

* @notice If the node is online but hasn't reported verification that day,

* @notice the smart contract needs to be notified through this function to update the status of the node today.

*

* @param node: address of the node to report daily active

*/

function nodeReportDailyActive(address node) external;

/**

* @notice After an attestation is reported, a group of nodes will be randomly selected through chainlink's VRF.

* @notice These nodes need to submit the verification within the specified time.

* @notice When a node is selected by VRF, the proof is submitted by calling `nodeReportVerification`.

* @notice The verification cannot be submitted repeatedly.

*

* @dev Only nodes chosen by VRF in this attestation.

* @dev Emits `NodeReportVerification`.

*

* @param attestationID: id of attestation

* @param index: index of this node in vrfChosen list of this attestation

* @param result: Whether the attestation is valid after being checked by the node.

*/

function nodeReportVerification(bytes32 attestationID, uint16 index, AttestationResult result) external;

/**

* @notice Batch reporting verification.

* @notice One address can collect multiple verifications and delegate reporting them in batches,

* @notice following the eip-712.

*

* @dev Emits `NodeReportVerificationBatch`.

*/

function nodeReportVerificationBatch(bytes32 attestationID, VerificationInfo[] calldata infos) external;

/**

* @notice If the NFT holder doesn't want to run the node to report the verification himself,

* @notice he can delegate the authority to others to run by calling `delegate`.

* @notice After delegating, NFT holders will give a proportion of rewards (10%) to the delegatee.

*

* @dev Emits `Delegate`.

*

* @param tokenID: tokenID of BluwhaleNft to be delegated.

* @param to: address of whom you want to delegate to

*/

function delegate(uint256 tokenID, address to) external;

/**

* @notice Specify a new delegatee to replace the current delegatee.

* @notice During the `redelegate`, the node may be triggered to exit.

*

* @dev Emits `Redelegate`.

* @dev When the node's delegation weight is reduced to 0, it will be forced offline. Emits `NodeClear`

*

* @param tokenID: tokenID of BluwhaleNft to be redelegated.

* @param to: address of whom you want to redelegate to

*/

function redelegate(uint256 tokenID, address to) external;

/**

* @notice Cancel current delegation.

* @notice During the `undelegate`, the node may be triggered to exit.

*

* @dev Emits `undelegate`.

* @dev When the node's delegation weight is reduced to 0, it will be forced offline. Emits `NodeClear`

*

* @param tokenID: tokenID of BluwhaleNft to be undelegated.

*/

function undelegate(uint256 tokenID) external;

/**

* @notice Claim rewards corresponding to a certain tokenID owned by you.

* @notice vault.rewardsWithdraw() will be called to transfer veBluwhale to the user.

* @notice After the user claim the reward, this BluwhaleNft cannot be redeemed.

*

* @dev Emits `ClaimRewards`.

*

* @param tokenID: The token ID that needs to be claimed rewards

*/

function claimRewards(uint256 tokenID) external;

/**

* @notice Check whether this tokenID has already claimed rewards.

*

* @param tokenID: token ID

* @return claimed: whether this tokenID has already claimed rewards

*/

function checkClaimed(uint256 tokenID) external view returns (bool);

/**

* @notice Get the index of today.

*/

function todayIndex() external view returns (uint32);

/**

* @notice Get the offset of today.

*/

function todayOffset() external view returns (uint256);

}

Last updated