Skip to content

Commit

Permalink
Create proof of liveness smart contract
Browse files Browse the repository at this point in the history
  • Loading branch information
andresaiello committed Sep 25, 2024
1 parent 9e35108 commit d653425
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 1 deletion.
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);
}

Check notice

Code scanning / Slither

Block timestamp Low

ProofOfLiveness.proveLiveness() uses timestamp for comparisons
Dangerous comparisons:
- currentTime < lastProofTime + PROOF_PERIOD

// 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;
}

Check notice

Code scanning / Slither

Block timestamp Low


// 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;

Check warning

Code scanning / Slither

Uninitialized local variables Medium

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;
}

Check notice

Code scanning / Slither

Block timestamp Low

}
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);
});

0 comments on commit d653425

Please sign in to comment.