- Install hardhat: https://hardhat.org/hardhat-runner/docs/getting-started#installation
- Clone the DLP Smart Contract Repo: https://github.com/vana-com/vana-dlp-smart-contracts/
- Install dependencies
yarn install
- Run tests to be sure everything is ok
npx hardhat test
- Create an
.env
file for the smart contract repo. You will need the owner address and private key. Customize the DLP name, token name, and token symbol as needed.
DEPLOYER_PRIVATE_KEY=8...7
OWNER_ADDRESS=0x3....1
SATORI_RPC_URL=https://rpc.satori.vana.org
DLP_NAME=Custom Data Liquidity Pool
DLP_TOKEN_NAME=Custom Data Autonomy Token
DLP_TOKEN_SYMBOL=CUSTOMDAT
- Deploy the DataLiquidityPoolsRoot smart contract
npx hardhat deploy --network satori --tags DLPRootDeploy
This will deploy the DataLiquidityPoolsRoot
smart contract using the recommended params for testing. If you need a different setup, you can change them in the deploy/dlpRoot.ts script.
- Verify the
DataLiquidityPoolsRoot
contract:
npx hardhat verify --network satori <data_liquidity_pools_root_address>
- Deploy the
DataLiquidityPool
andDataLiquidityPoolToken
smart contracts
npx hardhat deploy --network satori --tags DLPDeploy
This will deploy the DataLiquidityPool
and DataLiquidityPoolToken
smart contracts using the recommended params for testing. If you need a different setup, you can change them in the deploy/dlp-deploy.ts
script.
- Verify the
DataLiquidityPool
andDataLiquidityPoolToken
contracts:
npx hardhat verify --network satori <data_liquidity_pool_address>
npx hardhat verify --network satori <data_liquidity_pool_token_address> "<token_name>" <token_symbol> <owner_address>
If you get an error, it may be because the block explorer has already verified matching bytecode. Check your contract in the block explorer. If it is verified, you can ignore the error.
-
Congratulations, you've deployed the DLP & token smart contracts. You can confirm it's up by searching the address on the block explorer: https://satori.vanascan.io/address/<contract_address>.
-
Now you should configure the deployed DLP contract:
- Visit the Satori block explorer: https://satori.vanascan.io/address/<contract_address>
- Go to the "Write proxy" tab
- Connect your wallet (make sure it's the owner wallet used for deployment)
- Set the following parameters:
- Call
updateFileRewardDelay
and set it to 0 - Call
addRewardsForContributors
with a large value (e.g., 1000000000000000000000000 for 1 million tokens)
- Call
- For each function call, confirm the transaction in your wallet
These steps ensure that rewards can be claimed immediately and that there are sufficient tokens allocated for rewards.
- If you need to upgrade the
DataLiquidityPool
contract in the future, you can use thedlp-upgrade.ts
script:
npx hardhat deploy --network satori --tags DLPUpgrade
This will upgrade the DataLiquidityPool
contract to the latest version while preserving its state and address.
By following these steps, you can deploy the complete set of smart contracts (DataLiquidityPoolsRoot
, DataLiquidityPool
, and DataLiquidityPoolToken
) to the Satori network and verify them on the block explorer. The DataLiquidityPoolsRoot
contract manages the creation and reward distribution for multiple DLPs, while each DataLiquidityPool
contract handles validator registration, file uploads, and reward distribution within its specific pool.
Based on the provided Solidity contract, here is a README file in Markdown format for the DLPT
contract:
The DLPT
(DLP Token) contract is an ERC20 token with additional features such as minting permissions, an admin role, and a blocklist for addresses. It leverages OpenZeppelin's ERC20, ERC20Permit, ERC20Votes, and Ownable modules for extended functionality.
- Minting Control: Minting can be blocked permanently.
- Admin Management: Change and assign an admin who has special permissions.
- Blocklist Management: Add and remove addresses from a blocklist.
- Voting and Permit: Supports ERC20Votes and ERC20Permit extensions for governance and permit functionality.
MintBlocked()
AdminChanged(address indexed oldAdmin, address indexed newAdmin)
AddressBlocked(address indexed blockedAddress)
AddressUnblocked(address indexed unblockedAddress)
EnforceMintBlocked()
UnauthorizedAdminAction(address account)
UnauthorizedUserAction(address account)
constructor(address ownerAddress) ERC20("DLP Token", "DLPT") ERC20Permit("DLP Token") Ownable(ownerAddress)
you can modify the contract name and the constructor's arguments for deploying Token with your own name and symbol.
function mint(address to, uint256 amount) external virtual onlyOwner whenMintIsAllowed
Mints a specified amount of tokens to the given address.
function blockMint() external virtual onlyOwner whenMintIsAllowed
Blocks any future minting of tokens permanently.
function changeAdmin(address newAdmin) external virtual onlyOwner
Changes the admin address.
function blockAddress(address addressToBeBlocked) external virtual onlyAdmin
Adds an address to the blocklist.
function unblockAddress(address addressToBeUnblocked) external virtual onlyAdmin
Removes an address from the blocklist.
function blockListLength() external view returns(uint256)
Returns the number of addresses in the blocklist.
function blockListAt(uint256 _index) external view returns(address)
Returns the address at the specified index in the blocklist.
The Data Liquidity Pool smart contract is designed to manage the registration of validators, file uploading by data contributors, and reward distribution within a decentralized network. This contract ensures that validators can participate in maintaining the network's integrity and security while earning rewards for their contributions.
The Data Liquidity Pool contract facilitates several key functions:
- Validator Registration: Allows users to register as validators and participate in the network.
- Reward Distribution: Validators earn rewards based on their performance and contribution, distributed periodically.
- File uploads: Data contributors can upload files and earn rewards based on the quality of their data
function registerValidator(address validatorAddress,address validatorOwnerAddress, uint256 stakeAmount) external override whenNotPaused nonReentrant
Registers a new validator in the system. The caller must have enough Tokens to stake as part of the process. Once registered, the validator must be approved by the DLP owner in order to be eligible for validating files and for epoch rewards.
validatorAddress
(address): The address of the validator to be registered.validatorOwnerAddress
(address): The owner address of the validator.stakeAmount
(uint256): The amount of tokens to be staked by the validator.
- Checks if the validator is not already registered.
- Ensures the stake amount is above the minimum required.
- Transfers the stake amount from the sender to the contract.
- Updates the validator's information and status.
- Increases the total count of validators and updates the total staked amount.
- Emits the
ValidatorRegistered
event.
ValidatorRegistered(address validatorAddress, address validatorOwnerAddress, uint256 stakeAmount)
function approveValidator(address validatorAddress) public onlyOwner
Approves a registered validator and marks them as active.
validatorAddress
(address): The address of the validator to be approved.
- Creates epochs if necessary.
- Copies the current active validators list to a new list.
- Checks if the validator is in a registered state.
- Adds the validator to the new active validators list and marks them as active.
- Updates the validator's first block number.
- Sets the current epoch's validators list ID.
- Emits the
ValidatorApproved
event.
ValidatorApproved(address validatorAddress)
function inactivateValidator(address validatorAddress) public onlyValidatorOwner(validatorAddress)
Inactivates an active validator.
validatorAddress
(address): The address of the validator to be inactivated.
- Creates epochs if necessary.
- Checks if the validator is in an active state.
- Calls the internal
_inactivateValidator
function to process the inactivation.
ValidatorApproved(address validatorAddress)
function addFile(string memory url,string memory encryptedKey) external whenNotPaused
Adds a new file to the pool for validation.
url
(string): The URL of the file to be added.encryptedKey
(string): The encrypted key for the file.
- Creates epochs if necessary.
- Computes a hash of the file URL to ensure uniqueness.
- Checks if the file has already been added using the hash.
- Adds the file URL hash to the set of file URL hashes.
- Stores the file information including the contributor address, URL, encrypted key, and timestamp.
- Assigns the file to a validator based on the current epoch's validators list.
- Updates the validator's and contributor's information to track the new file.
- Emits the
FileAdded
event.
FileAdded(address contributorAddress, uint256 filesId)
function verifyFile(uint256 fileId,uint256 score, string memory metadata) external onlyActiveValidators
Verifies a file and assigns a score to it.
fileId
(uint256): The ID of the file to be verified.score
(uint256): The score assigned to the file.metadata
(string): Additional metadata related to the verification.
- Creates epochs if necessary.
- Checks if the file has already been verified.
- Retrieves the next file to verify for the validator.
- Ensures the file ID is valid and matches the expected file ID.
- Updates the file's verification information including the validator address, timestamp, score, and metadata.
- Increases the file's verification count.
- Calculates and assigns the reward for the file based on the score.
- Updates the validator's file verification index.
- Removes the validator from the list of validators with files to verify if all files have been verified and the validator is not active.
- Emits the
FileVerified
event.
FileVerified(address validatorAddress, uint256 fileId, uint256 score)