Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Create proof of liveness smart contract #190

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

contract ProofOfLiveness {
// Mapping to track the last time the user proved liveness
mapping(address => uint256) public lastProofTimestamp;

// Custom error for when a user has already proved liveness within the last 24 hours
error ProofWithinLast24Hours(uint256 lastProofTime);

// Event to log when liveness is proved
event LivenessProved(address indexed user, uint256 proofTimestamp);

// The function to prove liveness, can only be called once every 24 hours
function proveLiveness() external {
uint256 currentTime = block.timestamp;
uint256 lastProofTime = lastProofTimestamp[msg.sender];

// Check if the user has proved liveness within the last 24 hours
if (currentTime < lastProofTime + 24 hours) {
revert ProofWithinLast24Hours(lastProofTime);
}

// Update the last proof timestamp for the user
lastProofTimestamp[msg.sender] = currentTime;

// Emit an event to track the liveness proof
emit LivenessProved(msg.sender, currentTime);
}
Fixed Show fixed Hide fixed
andresaiello marked this conversation as resolved.
Show resolved Hide resolved

// Helper function to check if a user can prove liveness (returns true if 24 hours have passed)
function canProveLiveness(address user) external view returns (bool) {
uint256 currentTime = block.timestamp;
return currentTime >= lastProofTimestamp[user] + 24 hours;
}
Dismissed Show dismissed Hide dismissed
andresaiello marked this conversation as resolved.
Show resolved Hide resolved

// View function to return the liveness proof status for the last 5 periods (each 24 hours long)
function getLastFivePeriodsStatus(address user) external view returns (bool[5] memory) {
uint256 currentTime = block.timestamp;
uint256 lastProofTime = lastProofTimestamp[user];

bool[5] memory proofStatus;
Fixed Show fixed Hide fixed
uint256 periodDuration = 24 hours;

for (uint256 i = 0; i < 5; i++) {
// Calculate the start of the period (going back i * 24 hours)
uint256 periodStart = currentTime - (i * periodDuration);
uint256 periodEnd = periodStart - periodDuration;

// If the last proof timestamp falls within this period, mark it as true
if (lastProofTime >= periodEnd && lastProofTime < periodStart) {
proofStatus[i] = true;
} else {
proofStatus[i] = false;
}
}

return proofStatus;
}
Fixed Show fixed Hide fixed
andresaiello marked this conversation as resolved.
Show resolved Hide resolved
}
andresaiello marked this conversation as resolved.
Show resolved Hide resolved
3 changes: 2 additions & 1 deletion packages/zevm-app-contracts/data/addresses.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
"invitationManager": "0x3649C03C472B698213926543456E9c21081e529d",
"withdrawERC20": "0xa349B9367cc54b47CAb8D09A95836AE8b4D1d84E",
"ZetaXP": "0x5c25b6f4D2b7a550a80561d3Bf274C953aC8be7d",
"InstantRewards": "0x10DfEd4ba9b8F6a1c998E829FfC0325D533c80E3"
"InstantRewards": "0x10DfEd4ba9b8F6a1c998E829FfC0325D533c80E3",
"ProofOfLiveness": "0x2aD64D83827D102FCBBdEb92DEA91fCAB168Cdc2"
},
"zeta_mainnet": {
"disperse": "0x23ce409Ea60c3d75827d04D9db3d52F3af62e44d",
Expand Down
33 changes: 33 additions & 0 deletions packages/zevm-app-contracts/scripts/proof-of-liveness/deploy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { isProtocolNetworkName } from "@zetachain/protocol-contracts";
import { ethers, network } from "hardhat";

import { ProofOfLiveness__factory } from "../../typechain-types";
import { saveAddress } from "../address.helpers";
import { verifyContract } from "../explorer.helpers";

const networkName = network.name;

const deployProofOfLiveness = async () => {
if (!isProtocolNetworkName(networkName)) throw new Error("Invalid network name");

const ProofOfLivenessFactory = (await ethers.getContractFactory("ProofOfLiveness")) as ProofOfLiveness__factory;
const ProofOfLiveness = await ProofOfLivenessFactory.deploy();

await ProofOfLiveness.deployed();

console.log("ProofOfLiveness deployed to:", ProofOfLiveness.address);

saveAddress("ProofOfLiveness", ProofOfLiveness.address, networkName);

await verifyContract(ProofOfLiveness.address, []);
};

const main = async () => {
if (!isProtocolNetworkName(networkName)) throw new Error("Invalid network name");
await deployProofOfLiveness();
};

main().catch((error) => {
console.error(error);
process.exit(1);
});
andresaiello marked this conversation as resolved.
Show resolved Hide resolved
Loading