Dapp Use Cases
Farcaster Rate Limits
Introduction
Assertions
- Dapp Use Cases
- Implementation / Address Change
- Owner Change
- Constant Product
- Lending Health Factor
- Sum of all positions
- Timelock Verification
- Oracle Validation
- TWAP Deviation
- ERC4626 Assets to Shares
- ERC4626 Deposit and Withdraw
- Fee Calculations
- Price Within Ticks
- Liquidation Health Factor
- Panic State Validation
- Harvest Increases Balance
- Tokens Borrowed Invariant
- ERC20 Drain
- Ether Drain
- Farcaster Message Validity
- Farcaster Unique Username
- Farcaster Rate Limits
- Correct Withdraw
- Intra-tx Oracle Deviation
- Previous Hacks Assertions
Dapp Use Cases
Farcaster Rate Limits
Make sure that rate limits are respected
Use Case
Farcaster is a social media platform that allows users to post messages to a decentralized network. In a free to use platform like Farcaster, it is important to make sure that it’s not possible to DoS the platform.
Explanation
Check that rate limits are respected.
Code Example
// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
import {Assertion} from "../../lib/credible-std/src/Assertion.sol";
import {PhEvm} from "../../lib/credible-std/src/PhEvm.sol";
interface IFarcaster {
function getLastPostTimestamp(address user) external view returns (uint256);
function getUserPostCount(address user, uint256 timeWindow) external view returns (uint256);
function postMessage(address user, string calldata content) external;
}
contract FarcasterRateLimitAssertion is Assertion {
IFarcaster public farcaster = IFarcaster(address(0xbeef));
// Rate limit constants
uint256 constant POST_COOLDOWN = 1 minutes;
uint256 constant MAX_POSTS_PER_HOUR = 60;
uint256 constant HOUR = 1 hours;
function fnSelectors() external pure override returns (bytes4[] memory assertions) {
assertions = new bytes4[](1);
assertions[0] = this.assertRateLimit.selector;
}
function assertRateLimit() external {
PhEvm.CallInputs[] memory callInputs = ph.getCallInputs(address(farcaster), farcaster.postMessage.selector);
if (callInputs.length == 0) {
return;
}
for (uint256 i = 0; i < callInputs.length; i++) {
bytes memory data = callInputs[i].input;
address user = abi.decode(stripSelector(data), (address));
ph.forkPreState();
// Check cooldown between posts
uint256 lastPostTime = farcaster.getLastPostTimestamp(user);
require(block.timestamp >= lastPostTime + POST_COOLDOWN, "Posting too quickly");
// Check hourly post limit
uint256 hourlyPosts = farcaster.getUserPostCount(user, HOUR);
require(hourlyPosts < MAX_POSTS_PER_HOUR, "Exceeded hourly post limit");
}
}
function stripSelector(bytes memory input) internal pure returns (bytes memory) {
bytes memory paramData = new bytes(32);
for (uint256 i = 4; i < input.length; i++) {
paramData[i - 4] = input[i];
}
return paramData;
}
}
On this page