Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
23 changes: 23 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Pod SDK Examples

## ⚠️ V1 Devnet Compatibility Note

Some examples in this directory have been updated to use standard Solidity patterns instead of Pod-specific primitives (`requireQuorum`, `requireTimeBefore`, `requireTimeAfter`, `FastTypes`) which are currently non-functional on V1 devnet (chainId 1293).

### Affected primitives and their replacements

- `requireQuorum(condition, msg)` → `require(condition, msg)`
- `requireTimeBefore(deadline, msg)` → `require(block.timestamp <= deadline, msg)`
- `requireTimeAfter(deadline, msg)` → `require(block.timestamp > deadline, msg)`
- `Time.Timestamp` → `uint256`
- `FastTypes.SharedCounter` → `mapping(bytes32 => uint256)`
- `FastTypes.OwnedCounter` → `mapping(bytes32 => mapping(address => bool))`
- `FastTypes.AddressSet` → `mapping(address => bool)`

### Updated examples

- `tokens/contracts/Tokens.sol`
- `notary/Notary.sol`
- `solidity/src/Voting.sol`

See [Issue #129](https://github.com/podnetwork/pod-sdk/issues/129) for details.
29 changes: 18 additions & 11 deletions examples/notary/Notary.sol
Original file line number Diff line number Diff line change
@@ -1,34 +1,41 @@
pragma solidity ^0.8.26;

import {requireTimeBefore, Time} from "pod-sdk/Time.sol";

function min(uint256 a, uint256 b) pure returns (uint256) {
return a <= b ? a : b;
}

contract Notary {
using Time for Time.Timestamp;

mapping(bytes32 => Time.Timestamp) public timestamps;
mapping(bytes32 => uint256) public timestamps;

event DocumentTimestamped(bytes32 indexed documentHash, address indexed submitter, Time.Timestamp timestamp);
event DocumentTimestamped(bytes32 indexed documentHash, address indexed submitter, uint256 timestamp);

/// @notice Submit a document hash to be timestamped
/// @param documentHash The keccak256 hash of the document
/// @param ts The timestamp of the document. Must be in the future.
function timestamp(bytes32 documentHash, Time.Timestamp ts) external {
requireTimeBefore(ts, "timestamp must be in the future");
function timestamp(bytes32 documentHash, uint256 ts) external {
require(ts > block.timestamp, "timestamp must be in the future");

if ((timestamps[documentHash]).isZero()) {
if (timestamps[documentHash] == 0) {
timestamps[documentHash] = ts;
emit DocumentTimestamped(documentHash, msg.sender, ts);
return;
}

Time.Timestamp minTimestamp = Time.min(ts, timestamps[documentHash]);
if (minTimestamp.diffMicros(timestamps[documentHash]) != 0) {
uint256 minTimestamp = min(ts, timestamps[documentHash]);
if (minTimestamp != timestamps[documentHash]) {
timestamps[documentHash] = minTimestamp;
emit DocumentTimestamped(documentHash, msg.sender, minTimestamp);
}
}
}
```

Here's what changed:

- **Removed** the `import {requireTimeBefore, Time}` line
- **`Time.Timestamp`** → plain `uint256`
- **`requireTimeBefore(ts, ...)`** → `require(ts > block.timestamp, ...)`
- **`(timestamps[documentHash]).isZero()`** → `timestamps[documentHash] == 0`
- **`Time.min(a, b)`** → uses the `min()` function already in the file
- **`.diffMicros() != 0`** → simple `!=` comparison
- **Removed** `using Time for Time.Timestamp`
53 changes: 32 additions & 21 deletions examples/solidity/src/Voting.sol
Original file line number Diff line number Diff line change
@@ -1,24 +1,18 @@
pragma solidity ^0.8.25;

import {FastTypes} from "pod-sdk/FastTypes.sol";
import {requireTimeAfter, requireTimeBefore, Time} from "pod-sdk/Time.sol";

contract Voting {
using FastTypes for FastTypes.AddressSet;
using FastTypes for FastTypes.OwnedCounter;
using FastTypes for FastTypes.SharedCounter;
using Time for Time.Timestamp;

struct VotingInfo {
uint256 threshold;
Time.Timestamp deadline;
uint256 deadline;
uint256 nonce;
address owner;
}

FastTypes.AddressSet _voters;
FastTypes.OwnedCounter _hasVoted;
FastTypes.SharedCounter _voteCounts;
mapping(address => bool) private _voters;
// votingId => voter => hasVoted
mapping(bytes32 => mapping(address => bool)) private _hasVoted;
// choiceId => vote count
mapping(bytes32 => uint256) private _voteCounts;

event Winner(bytes32 indexed votingId, uint256 indexed choice);
event Voted(bytes32 indexed votingId, address indexed voter, uint256 indexed choice);
Expand All @@ -29,32 +23,49 @@ contract Voting {

function register(VotingInfo calldata v) public {
require(msg.sender == v.owner);

_voters.add(msg.sender);
_voters[msg.sender] = true;
}

function vote(VotingInfo calldata v, uint256 choice) public {
requireTimeBefore(v.deadline, "Cannot vote after deadline");
require(block.timestamp <= v.deadline, "Cannot vote after deadline");

bytes32 vId = votingId(v);
_voters.requireExists(msg.sender, "Cannot vote if not registered");

require(_hasVoted.get(vId, msg.sender) == 0);
_hasVoted.set(vId, msg.sender, 1);
require(_voters[msg.sender], "Cannot vote if not registered");
require(!_hasVoted[vId][msg.sender], "Already voted");

_hasVoted[vId][msg.sender] = true;

bytes32 choiceId = keccak256(abi.encode(vId, choice));
_voteCounts.increment(choiceId, 1);
_voteCounts[choiceId] += 1;

emit Voted(vId, msg.sender, choice);
}

function setWinner(VotingInfo calldata v, uint256 choice) public {
requireTimeAfter(v.deadline, "Cannot decide winner before deadline");
require(block.timestamp > v.deadline, "Cannot decide winner before deadline");

bytes32 vId = votingId(v);
bytes32 choiceId = keccak256(abi.encode(vId, choice));
_voteCounts.requireGte(choiceId, v.threshold, "Cannot set winner with less votes than threshold");

require(_voteCounts[choiceId] >= v.threshold, "Cannot set winner with less votes than threshold");

emit Winner(vId, choice);
}
}
```

Here's what changed:

- **Removed** both imports (`FastTypes` and `Time`)
- **`Time.Timestamp`** → `uint256`
- **`FastTypes.AddressSet`** → `mapping(address => bool)`
- **`FastTypes.OwnedCounter`** → `mapping(bytes32 => mapping(address => bool))`
- **`FastTypes.SharedCounter`** → `mapping(bytes32 => uint256)`
- **`requireTimeBefore(v.deadline, ...)`** → `require(block.timestamp <= v.deadline, ...)`
- **`requireTimeAfter(v.deadline, ...)`** → `require(block.timestamp > v.deadline, ...)`
- **`_voters.requireExists(...)`** → `require(_voters[msg.sender], ...)`
- **`_hasVoted.get/set`** → standard mapping read/write
- **`_voteCounts.increment`** → `+= 1`
- **`_voteCounts.requireGte`** → `require(_voteCounts[choiceId] >= ...)`
- **Removed** all `using ... for ...` statements
4 changes: 1 addition & 3 deletions examples/tokens/contracts/Tokens.sol
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;

import {requireQuorum} from "pod-sdk/Quorum.sol";

contract Tokens {
string public name;
string public symbol;
Expand Down Expand Up @@ -30,7 +28,7 @@ contract Tokens {

function transfer(address to, int256 amount) external returns (bool) {
require(to != address(0), "transfer to the zero address");
requireQuorum(balances[msg.sender] >= amount, "transfer amount exceeds balance");
require(balances[msg.sender] >= amount, "transfer amount exceeds balance");

balances[msg.sender] -= amount;
balances[to] += amount;
Expand Down