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

update

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