Commit e5d70fb2 authored by 贾浩@五瓣科技's avatar 贾浩@五瓣科技

update

parent 992770e9
......@@ -15,4 +15,6 @@ artifacts
*.abi
*.go
\ No newline at end of file
*.go
.DS_Store
abi.json
\ No newline at end of file
......@@ -2,26 +2,24 @@
pragma solidity ^0.8.20;
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {MerkleProof} from "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {Pausable} from "@openzeppelin/contracts/utils/Pausable.sol";
import {ReentrancyGuard} from "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import {MerkleProof} from "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol";
import {IValidator} from "./interface/IValidator.sol";
import {IDistribution} from "./interface/IDistribution.sol";
contract Distribution is IDistribution, Ownable, Pausable, ReentrancyGuard {
constructor() Ownable(msg.sender) {
}
IValidator public validator;
IERC20 public token = IERC20(address(0xfFb096e2B90324FFcCbaf987BdD724462c0aE18c));
mapping(address => uint256) public userClaimed;
event Claimed(address indexed addr, uint256 indexed amount, uint256 indexed totalClaimedAmount);
constructor(address _validator) Ownable(msg.sender) {
validator = IValidator(_validator);
}
function setPause() public onlyOwner {
_pause();
}
......@@ -30,8 +28,8 @@ contract Distribution is IDistribution, Ownable, Pausable, ReentrancyGuard {
_unpause();
}
function withdraw(address addr) public onlyOwner {
token.transfer(addr, token.balanceOf(address(this)));
function withdraw(address addr, uint256 amount) public onlyOwner {
transferToken(addr, amount);
}
function claim(bytes32[] calldata proof, uint256 userAllAmount) public whenNotPaused nonReentrant {
......@@ -40,11 +38,20 @@ contract Distribution is IDistribution, Ownable, Pausable, ReentrancyGuard {
uint256 userCanClaimAmount = userAllAmount - userClaimed[msg.sender];
userClaimed[msg.sender] = userAllAmount;
token.transfer(msg.sender, userCanClaimAmount);
transferToken(msg.sender, userCanClaimAmount);
emit Claimed(msg.sender, userCanClaimAmount, userAllAmount);
}
function transferToken(address addr, uint256 amount) internal {
(bool success, ) = addr.call{value: amount}("");
require(success, "Transfer failed");
}
function _merkleRoot() internal returns (bytes32){
return validator.getMerkleRoot();
}
function claimedOf() public view returns (uint256){
return userClaimed[msg.sender];
}
}
\ No newline at end of file
......@@ -13,8 +13,8 @@ contract Validator is IValidator, Ownable {
bytes32 public merkleRoot; // 当前最新的 merkle root
bytes32 public merkleSumRoot; // 当前最新的 merkle sum root
uint256 public merkleRootThreshold = 1; // 多节点提交时,生效阈值
uint256 public dailyMerkleRootSubmitCount = 0; // 当天已提交次数
uint256 public merkleRootThreshold ; // 多节点提交时,生效阈值
uint256 public dailyMerkleRootSubmitCount; // 当天已提交次数
uint256 public lastMerkleRootUpdate; // 上次 merkle root 更新时间
// 记录每天每个 merkle root 提交次数 2023-01-01 -> hash(merkleRoot, merkleSumRoot) -> 1
......@@ -27,11 +27,17 @@ contract Validator is IValidator, Ownable {
mapping(uint256 => bytes32) public dailyMerkleRootMap;
// 记录每天的 merkle sum root
mapping(uint256 => bytes32) public dailyMerkleSumRootMap;
uint256 public dailyDistribution = 10000 ether;
// 记录每天的工作量总数
mapping(uint256 => uint256) public dailyWorkloadMap;
// 记录每天的奖励金额
mapping(uint256 => uint256) public dailyRewardMap;
// 每天奖励金额
uint256 public dailyReward;
constructor() Ownable(msg.sender) {
validatorSet.add(msg.sender); // for test
merkleRootThreshold = 1;
dailyReward = 1 ether;
validatorSet.add(msg.sender);
}
modifier onlyValidator() {
......@@ -39,45 +45,47 @@ contract Validator is IValidator, Ownable {
_;
}
event MerkleRootChanged(uint256 date, bytes32 merkleRoot, bytes32 merkleSumRoot);
event MerkleRootChanged(uint256 date, bytes32 merkleRoot, bytes32 merkleSumRoot, uint256 totalWorkload);
event MerkleRootThresholdChanged(uint256 merkleRootThreshold);
event MerkleRootSubmitted(address indexed addr, bytes32 merkleRoot, bytes32 merkleSumRoot, uint256 indexed count, uint256 indexed dailySubmitCount);
event DailyDistributionChanged(uint256 dailyDistribution);
event DailyRewardChanged(uint256 dailyReward);
event ValidatorChanged(address indexed addr, bool indexed ok, uint256 indexed count);
function getMerkleRoot() public view returns (bytes32){
return merkleRoot;
}
function getWorkloadDistribution(uint256 dailyWorkload) view public returns (uint256) {
function getWorkloadReward(uint256 dailyWorkload) view public returns (uint256) {
if (dailyWorkload == 0) {
return 0;
}
return dailyDistribution / dailyWorkload;
return dailyReward / dailyWorkload;
}
function submitMerkleRoot(uint256 _date, bytes32 _merkleRoot, bytes32 _merkleSumRoot) public onlyValidator {
require(dailyMerkleRootSubmitCount <= validatorSet.length(), "Too many submissions");
require(!dailyMerkleRootSubmittedMap[_date][msg.sender], "Already submitted");
function submitMerkleRoot(uint256 _date, bytes32 _merkleRoot, bytes32 _merkleSumRoot, uint256 _totalWorkload) public onlyValidator {
// require(dailyMerkleRootSubmitCount <= validatorSet.length(), "Too many submissions");
// require(!dailyMerkleRootSubmittedMap[_date][msg.sender], "Already submitted");
// check already verified
if (dailyMerkleRootVerifiedMap[_date]) {
return;
}
require(block.timestamp - lastMerkleRootUpdate >= (3600 * 24 - 300), "Too soon");
bytes32 rootHash = keccak256(abi.encodePacked(_merkleRoot, _merkleSumRoot));
// require(block.timestamp - lastMerkleRootUpdate >= (3600 * 24 - 300), "Too soon");
bytes32 msgHash = keccak256(abi.encodePacked(_merkleRoot, _merkleSumRoot, _totalWorkload));
dailyMerkleRootSubmitCountMap[_date][rootHash] ++;
dailyMerkleRootSubmitCountMap[_date][msgHash] ++;
dailyMerkleRootSubmittedMap[_date][msg.sender] = true;
dailyMerkleRootSubmitCount ++;
if (dailyMerkleRootSubmitCountMap[_date][rootHash] >= merkleRootThreshold) {
if (dailyMerkleRootSubmitCountMap[_date][msgHash] >= merkleRootThreshold) {
dailyMerkleRootVerifiedMap[_date] = true;
_setMerkleRoot(_date, _merkleRoot, _merkleSumRoot);
dailyWorkloadMap[_date] = _totalWorkload;
dailyRewardMap[_date] = dailyReward;
lastMerkleRootUpdate = block.timestamp;
dailyMerkleRootSubmitCount = 0;
emit MerkleRootChanged(_date, _merkleRoot, _merkleSumRoot);
emit MerkleRootChanged(_date, _merkleRoot, _merkleSumRoot, _totalWorkload);
}
emit MerkleRootSubmitted(msg.sender, _merkleRoot, _merkleSumRoot, dailyMerkleRootSubmitCountMap[_date][rootHash], dailyMerkleRootSubmitCount);
emit MerkleRootSubmitted(msg.sender, _merkleRoot, _merkleSumRoot, dailyMerkleRootSubmitCountMap[_date][msgHash], dailyMerkleRootSubmitCount);
}
function _setMerkleRoot(uint256 _date, bytes32 _merkleRoot, bytes32 _merkleSumRoot) internal {
......@@ -87,13 +95,13 @@ contract Validator is IValidator, Ownable {
dailyMerkleSumRootMap[_date] = _merkleSumRoot;
}
function setDailyDistribution(uint256 _dailyDistribution) public onlyOwner {
dailyDistribution = _dailyDistribution;
emit DailyDistributionChanged(_dailyDistribution);
function setDailyReward(uint256 _dailyReward) public onlyOwner {
dailyReward = _dailyReward;
emit DailyRewardChanged(_dailyReward);
}
function getDailyDistribution() public view returns (uint256) {
return dailyDistribution;
function getDailyReward() public view returns (uint256) {
return dailyReward;
}
function setRootThreshold(uint256 _merkleRootThreshold) public onlyOwner {
......@@ -122,11 +130,20 @@ contract Validator is IValidator, Ownable {
validatorSet.remove(addr);
}
function getValidatores() public view returns (address[] memory) {
function getValidators() public view returns (address[] memory) {
return validatorSet.values();
}
function isValidator(address addr) public view returns (bool) {
return validatorSet.contains(addr);
}
function getWorkloadByDate(uint256 _date) public view returns (uint256) {
return dailyWorkloadMap[_date];
}
function getRewardByDate(uint256 _date) public view returns (uint256) {
return dailyRewardMap[_date];
}
}
\ No newline at end of file
......@@ -4,9 +4,9 @@ pragma solidity ^0.8.20;
interface IValidator {
function getMerkleRoot() external returns (bytes32);
function submitMerkleRoot(uint256 _date, bytes32 _merkleRoot, bytes32 _merkleSumRoot) external;
function submitMerkleRoot(uint256 _date, bytes32 _merkleRoot, bytes32 _merkleSumRoot, uint256 totalWorkload) external;
function getDailyDistribution() external view returns (uint256);
function getDailyReward() external view returns (uint256);
function setDailyDistribution(uint256 _dailyDistribution) external;
function setDailyReward(uint256 _dailyReward) external;
}
\ No newline at end of file
require("@nomicfoundation/hardhat-toolbox");
require('dotenv').config()
/** @type import('hardhat/config').HardhatUserConfig */
module.exports = {
solidity: {
......@@ -14,7 +13,7 @@ module.exports = {
},
networks: {
testnet: {
url: 'https://1rpc.io/holesky',
url: 'https://dev.rpc.agicoin.ai',
accounts: process.env.PRIVATE_KEY ? [process.env.PRIVATE_KEY] : []
}
},
......
This diff is collapsed.
......@@ -8,10 +8,15 @@ const hre = require("hardhat");
async function main() {
const Storage = await hre.ethers.getContractFactory("AddressStorage");
const storage = Storage.attach("0x7Cd36Bc2a477f60A14f08442179B2f626bE026Ea")
const storage = Storage.attach("0xA0ec84eCa14CD23afD5D7ba973390E83F0Cbe89A")
const ret = await storage.setContainerAddress("0x7Cd36Bc2a477f60A14f08442179B2f626bE026Ea", true);
console.log(ret.hash);
const ret2 = await storage.setContainerAddress("0x0Fb196385c8826e3806ebA2cA2cb78B26E08fEEe", true);
console.log(ret2.hash);
const ret3 = await storage.setNmAddress("0xE0785611500B582cCE651c17477a408Dd0057D30", true);
console.log(ret3.hash);
}
// We recommend this pattern to be able to use async/await everywhere
......
......@@ -4,23 +4,31 @@
// You can also run a script with `npx hardhat run <script>`. If you do that, Hardhat
// will compile your contracts, add the Hardhat Runtime Environment's members to the
// global scope, and execute the script.
const hre = require("hardhat");
// const hre = require("hardhat");
const {ethers} = require("hardhat")
async function main() {
const Storage = await hre.ethers.getContractFactory("AddressStorage");
// 部署 storage
const Storage = await ethers.getContractFactory("AddressStorage");
const storage = await Storage.deploy();
await storage.waitForDeployment();
console.log(`Storage deployed to ${storage.target}`);
// 部署 storage 结束
const Witness = await hre.ethers.getContractFactory("Witness");
const witness = await Witness.deploy();
await witness.waitForDeployment();
console.log(`Witness deployed to ${witness.target}`);
// 部署 Validator
const Validator = await ethers.getContractFactory("Validator");
const validator = await Validator.deploy();
await validator.waitForDeployment();
console.log(`Validator deployed to ${validator.target}`);
// 部署 Validator 结束
// const Distribution = await hre.ethers.getContractFactory("Distribution");
// const distribution = await Distribution.deploy();
// await distribution.waitForDeployment();
// console.log(`Distribution deployed to ${distribution.target}`);
// 部署 Distribution
const Distribution = await ethers.getContractFactory("Distribution");
const distribution = await Distribution.deploy(await validator.getAddress());
await distribution.waitForDeployment();
console.log(`Distribution deployed to ${distribution.target}`);
// 部署 Distribution 结束
}
// We recommend this pattern to be able to use async/await everywhere
......@@ -29,3 +37,7 @@ main().catch((error) => {
console.error(error);
process.exitCode = 1;
});
// Storage deployed to 0xA0ec84eCa14CD23afD5D7ba973390E83F0Cbe89A
// Validator deployed to 0x7CBD03ecfA9093F83150E9625A25B00F555c81F7
// Distribution deployed to 0xb85D8fD67b286632FbeBdAE36fdA135e97391f0D
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment