From 905cb8778e314278e928f0864b6cbe5063db4208 Mon Sep 17 00:00:00 2001 From: ross <92001561+z0r0z@users.noreply.github.com> Date: Tue, 17 Dec 2024 14:01:54 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=A4=BA=20compile=20plus=20nits?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gas-snapshot | 3 +-- README.md | 28 ++-------------------------- foundry.toml | 5 ++--- src/bounty.sol | 43 +++++++++++++++++++++++++------------------ test/bounty.t.sol | 4 ++++ 5 files changed, 34 insertions(+), 49 deletions(-) diff --git a/.gas-snapshot b/.gas-snapshot index 034ef9d..d918433 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -1,2 +1 @@ -Tester:test(string) (runs: 256, μ: 47790, ~: 24790) -TesterTest:testTest() (gas: 29940) \ No newline at end of file +BountyTest:testDeploy() (gas: 2377346) \ No newline at end of file diff --git a/README.md b/README.md index 2da1b91..83f6480 100644 --- a/README.md +++ b/README.md @@ -1,37 +1,13 @@ -# [zenplate](https://github.com/z0r0z/zenplate) [![License: AGPL-3.0-only](https://img.shields.io/badge/License-AGPL-black.svg)](https://opensource.org/license/agpl-v3/) [![solidity](https://img.shields.io/badge/solidity-%5E0.8.25-black)](https://docs.soliditylang.org/en/v0.8.25/) [![Foundry](https://img.shields.io/badge/Built%20with-Foundry-000000.svg)](https://getfoundry.sh/) ![tests](https://github.com/z0r0z/zenplate/actions/workflows/ci.yml/badge.svg) +# [bounties](https://github.com/NaniDAO/bounties) [![License: AGPL-3.0-only](https://img.shields.io/badge/License-AGPL-black.svg)](https://opensource.org/license/agpl-v3/) [![solidity](https://img.shields.io/badge/solidity-%5E0.8.28-black)](https://docs.soliditylang.org/en/v0.8.28/) [![Foundry](https://img.shields.io/badge/Built%20with-Foundry-000000.svg)](https://getfoundry.sh/) ![tests](https://github.com/NaniDAO/bounties/actions/workflows/ci.yml/badge.svg) -Simpler foundry template. +simple onchain bounties for daos ## Getting Started -Click [`use this template`](https://github.com/z0r0z/zenplate/generate) to start. - Run: `curl -L https://foundry.paradigm.xyz | bash && source ~/.bashrc && foundryup` Build the foundry project with `forge build`. Run tests with `forge test`. Measure gas with `forge snapshot`. Format with `forge fmt`. -## GitHub Actions - -Contracts will be tested and gas measured on every push and pull request. - -You can edit the CI script in [.github/workflows/ci.yml](./.github/workflows/ci.yml). - -## Blueprint - -```txt -lib -├─ forge-std — https://github.com/foundry-rs/forge-std -src -├─ Tester — Tester Contract -test -└─ Tester.t - Test Contract -``` - -## Notable Mentions - -- [femplate](https://github.com/refcell/femplate) -- [prb-foundry-template](https://github.dev/PaulRBerg/foundry-template) - ## Disclaimer *These smart contracts and testing suite are being provided as is. No guarantee, representation or warranty is being made, express or implied, as to the safety or correctness of anything provided herein or through related user interfaces. This repository and related code have not been audited and as such there can be no assurance anything will work as intended, and users may experience delays, failures, errors, omissions, loss of transmitted information or loss of funds. The creators are not liable for any of the foregoing. Users should proceed with caution and use at their own risk.* diff --git a/foundry.toml b/foundry.toml index b88591d..bd1bfe2 100644 --- a/foundry.toml +++ b/foundry.toml @@ -5,14 +5,13 @@ evm_version = "cancun" optimizer = true optimizer_runs = 9_999_999 +via_ir = true + remappings = [ "@solady=lib/solady/", "@forge=lib/forge-std/src/" ] -[profile.via-ir] -via_ir = true - [fmt] line_length = 100 diff --git a/src/bounty.sol b/src/bounty.sol index 898400f..25c3997 100644 --- a/src/bounty.sol +++ b/src/bounty.sol @@ -1,14 +1,14 @@ // SPDX-License-Identifier: AGPL-3.0-only pragma solidity ^0.8.19; -import {Ownable} from "@solady/src/auth/Ownable.sol"; +import {Base64} from "@solady/src/utils/Base64.sol"; import {ERC721} from "@solady/src/tokens/ERC721.sol"; +import {Ownable} from "@solady/src/auth/Ownable.sol"; import {LibString} from "@solady/src/utils/LibString.sol"; -import {Base64} from "@solady/src/utils/Base64.sol"; /// @notice Simple NFT contract for minting bounties. /// @dev Emojis also used for people that can't read. -contract bounty is Ownable, ERC721 { +contract bounty is ERC721, Ownable { using LibString for uint256; enum Status { @@ -20,19 +20,19 @@ contract bounty is Ownable, ERC721 { } struct Bounty { - string emojis; - string text; - address token; - uint256 amount; - Status status; - address watcher; + string emojis; // pictoral + string text; // basic gist + address token; // to grant + uint256 amount; // the sum + Status status; // id state + address watcher; // admins } uint256[] public bounties; mapping(uint256 tokenId => Bounty) public requests; constructor() payable { - _initializeOwner(msg.sender); + _initializeOwner(tx.origin); // Helps factory. } function name() public pure override(ERC721) returns (string memory) { @@ -43,13 +43,15 @@ contract bounty is Ownable, ERC721 { return unicode"⌘"; } - function pendingRequest(string calldata emojis, string calldata text) + error Exists(); + + function propose(string calldata emojis, string calldata text) public returns (uint256 tokenId) { tokenId = uint256(keccak256(abi.encodePacked(emojis, text))); - if (requests[tokenId].status != Status.None) revert("!none"); - requests[tokenId] = Bounty(emojis, text, address(0), 0, Status.Pending, owner());; + if (requests[tokenId].status != Status.None) revert Exists(); + requests[tokenId] = Bounty(emojis, text, address(0), 0, Status.Pending, owner()); bounties.push(tokenId); } @@ -59,22 +61,27 @@ contract bounty is Ownable, ERC721 { address token, uint256 amount, address watcher - ) public onlyOwner { - uint256 tokenId = uint256(keccak256(abi.encodePacked(emojis, text))); + ) public onlyOwner returns (uint256 tokenId) { + tokenId = uint256(keccak256(abi.encodePacked(emojis, text))); _mint(watcher, tokenId); requests[tokenId] = Bounty(emojis, text, token, amount, Status.Approved, watcher); if (requests[tokenId].status == Status.None) bounties.push(tokenId); } + error NotPending(); + function reject(uint256 tokenId) public onlyOwner { - if (requests[tokenId].status != Status.Pending) revert("!pending"); + if (requests[tokenId].status != Status.Pending) revert NotPending(); requests[tokenId].status = Status.Rejected; } + error NotApproved(); + error NotWatcher(); + function complete(uint256 tokenId, address recipient) public { Bounty storage _bounty = requests[tokenId]; - if (_bounty.status != Status.Approved) revert("!approved"); - if (_bounty.watcher != msg.sender) revert("!watcher"); + if (_bounty.status != Status.Approved) revert NotApproved(); + if (_bounty.watcher != msg.sender) revert NotWatcher(); _bounty.status = Status.Completed; transferFrom(_bounty.watcher, recipient, tokenId); } diff --git a/test/bounty.t.sol b/test/bounty.t.sol index 53fd2fc..d947fcb 100644 --- a/test/bounty.t.sol +++ b/test/bounty.t.sol @@ -15,4 +15,8 @@ contract BountyTest is Test { // vm.createSelectFork(vm.rpcUrl('arbi')); // Arbitrum EthL2 fork. _bounty = new bounty(); } + + function testDeploy() public payable { + new bounty(); + } }