Skip to content
DailyGM

DailyGM

Social

Created on 30th July 2025

•

DailyGM

DailyGM

Social

The problem DailyGM solves

At DailyGM, we're focusing on the challenge of fostering consistent user engagement and community building in the Web3 space. Many dApps struggle to maintain long-term interaction without incentives or complex gamification. Our goal is to create a simple yet effective way for users to connect daily through sending 'GMs' and expressing their mood, without relying on rewards or rankings.

Challenges I ran into

One of the main challenges we faced was implementing the user streak feature. Tracking consecutive daily 'GMs' onchain required careful design to ensure that the streaks reset correctly after a missed day. Initially, we struggled with accurately handling time zones and ensuring that the streak would increment only once per day. This led to unexpected behavior, where streaks were either not resetting or being incorrectly calculated.

To overcome this, we had to adjust the contract logic to base the streak on block timestamps and fine-tune how we handle date comparisons. By incorporating more precise checks, we ensured the streak feature worked as intended, providing users with a smooth and accurate experience.

Smart Contract Address(es)

´´´
contract ContractTest is ERC721, ERC721Enumerable, ERC721Pausable, Ownable {
uint256 private _nextTokenId;
uint internal totalUsers;
event Mint(address indexed user, uint256 timestamp, uint totalSupply, uint totalUsers);
event Mood(address indexed user, string mood);

struct User {
    address addr;
    uint256[] gms;
}

mapping (address => User) public Users;
mapping (address => bool) public registeredAddress;
mapping (address => string) public moodList;

constructor()
    ERC721("DailyGM", "GM")
    Ownable(msg.sender)
{}

function _baseURI() internal pure override returns (string memory) {
    return "";
}

function pause() public onlyOwner {
    _pause();
}

function unpause() public onlyOwner {
    _unpause();
}

function mintGM() public {
    require(isNextDay(msg.sender), "You Can Only GM Once A Day");

    if (!registeredAddress[msg.sender]) {
        Users[msg.sender].addr = msg.sender;
        Users[msg.sender].gms.push(block.timestamp);

        registeredAddress[msg.sender] = true;
        totalUsers += 1; 
    } else {
        Users[msg.sender].gms.push(block.timestamp);
    }

    uint256 tokenId = _nextTokenId++;
    _safeMint(msg.sender, tokenId);

    emit Mint(msg.sender, block.timestamp, totalSupply(), totalUsers);
}

function getGms(address user) external view returns (uint256[] memory) {
    return Users[user].gms;
}

function getLastGm(address user) internal view returns (uint256) {
    if (Users[user].gms.length > 0) {
        return Users[user].gms[Users[user].gms.length - 1];
    }
    return 0;
}

function isNextDay(address user) internal view returns (bool) {
    uint256 lastMintDate = getLastGm(user);

    if (lastMintDate == 0) {
        return true;
    }

    uint256 _lastMintDay = lastMintDate / 1 days;
    uint256 currentDay = block.timestamp / 1 days;

    return currentDay > _lastMintDay;
}

function setMood(string memory _mood) public payable {
    require(msg.value == 0.0001 ether, "0.0001 ETH is required");
    moodList[msg.sender] = _mood;

    emit Mood(msg.sender, _mood);
}

function getMood(address _addr) public view returns (string memory) {
    return moodList[_addr];
}

function withdraw(address payable _addr) external payable onlyOwner {
    _addr.transfer(address(this).balance);
}

function _update(address to, uint256 tokenId, address auth)
    internal
    override(ERC721, ERC721Enumerable, ERC721Pausable)
    returns (address)
{
    return super._update(to, tokenId, auth);
}

function _increaseBalance(address account, uint128 value)
    internal
    override(ERC721, ERC721Enumerable)
{
    super._increaseBalance(account, value);
}

function supportsInterface(bytes4 interfaceId)
    public
    view
    override(ERC721, ERC721Enumerable)
    returns (bool)
{
    return super.supportsInterface(interfaceId);
}

}
´´´

Other Onchain Proof

90 users and more than 170 onchain GMs minted!

Contract Address: 0xdAF63bDE4225380431f8e97a3D4c70a59a52BA54

image

Tracks Applied (1)

Top 5 Live Consumer Apps

Generating user onchain activity.

Cheer Project

Cheering for a project means supporting a project you like with as little as 0.0025 ETH. Right now, you can Cheer using ETH on Arbitrum, Optimism and Base.

Discussion

Builders also viewed

See more projects on Devfolio