Skip to content
Merged
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
38 changes: 38 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: CI

permissions: {}

on:
push:
pull_request:
workflow_dispatch:

env:
FOUNDRY_PROFILE: ci

jobs:
check:
name: Foundry project
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v5
with:
persist-credentials: false
submodules: recursive

- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1

- name: Show Forge version
run: forge --version

- name: Run Forge fmt
run: forge fmt --check

- name: Run Forge build
run: forge build --sizes

- name: Run Forge tests
run: forge test -vvv
14 changes: 14 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Compiler files
cache/
out/

# Ignores development broadcast logs
!/broadcast
/broadcast/*/31337/
/broadcast/**/dry-run/

# Docs
docs/

# Dotenv file
.env
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "lib/forge-std"]
path = lib/forge-std
url = https://github.com/foundry-rs/forge-std
66 changes: 66 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
## Foundry

**Foundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust.**

Foundry consists of:

- **Forge**: Ethereum testing framework (like Truffle, Hardhat and DappTools).
- **Cast**: Swiss army knife for interacting with EVM smart contracts, sending transactions and getting chain data.
- **Anvil**: Local Ethereum node, akin to Ganache, Hardhat Network.
- **Chisel**: Fast, utilitarian, and verbose solidity REPL.

## Documentation

https://book.getfoundry.sh/

## Usage

### Build

```shell
$ forge build
```

### Test

```shell
$ forge test
```

### Format

```shell
$ forge fmt
```

### Gas Snapshots

```shell
$ forge snapshot
```

### Anvil

```shell
$ anvil
```

### Deploy

```shell
$ forge script script/Counter.s.sol:CounterScript --rpc-url <your_rpc_url> --private-key <your_private_key>
```

### Cast

```shell
$ cast <subcommand>
```

### Help

```shell
$ forge --help
$ anvil --help
$ cast --help
```
8 changes: 8 additions & 0 deletions foundry.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"lib/forge-std": {
"tag": {
"name": "v1.15.0",
"rev": "0844d7e1fc5e60d77b68e469bff60265f236c398"
}
}
}
10 changes: 10 additions & 0 deletions foundry.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[profile.default]
src = "src"
out = "out"
libs = ["lib"]
solc = "0.8.28"
evm_version = "cancun"

[rpc_endpoints]
base = "https://mainnet.base.org"
base_sepolia = "https://sepolia.base.org"
1 change: 1 addition & 0 deletions lib/forge-std
Submodule forge-std added at 0844d7
17 changes: 17 additions & 0 deletions src/StoryFactory.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;

import {IMCV2_Bond} from "./interfaces/IMCV2_Bond.sol";
import {IERC20} from "./interfaces/IERC20.sol";

/// @title StoryFactory — PlotLink storyline and plot management
/// @notice Placeholder — full implementation in subsequent tickets
contract StoryFactory {
IMCV2_Bond public immutable BOND;
IERC20 public immutable PLOT_TOKEN;

constructor(address _bond, address _plotToken) {
BOND = IMCV2_Bond(_bond);
PLOT_TOKEN = IERC20(_plotToken);
}
}
11 changes: 11 additions & 0 deletions src/interfaces/IERC20.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;

/// @title IERC20 — Minimal ERC-20 interface for StoryFactory interactions
interface IERC20 {
function approve(address spender, uint256 amount) external returns (bool);
function transfer(address to, uint256 amount) external returns (bool);
function transferFrom(address from, address to, uint256 amount) external returns (bool);
function balanceOf(address account) external view returns (uint256);
function allowance(address owner, address spender) external view returns (uint256);
}
53 changes: 53 additions & 0 deletions src/interfaces/IMCV2_Bond.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;

/// @title IMCV2_Bond — Interface for Mint Club V2 Bond contract on Base
/// @dev Deployed at 0xc5a076cad94176c2996B32d8466Be1cE757FAa27
/// @dev Source: github.com/Steemhunt/mint.club-v2-contract

struct TokenParams {
string name;
string symbol;
}

struct BondParams {
uint16 mintRoyalty;
uint16 burnRoyalty;
address reserveToken;
uint128 maxSupply;
uint128[] stepRanges;
uint128[] stepPrices;
}

interface IMCV2_Bond {
/// @notice Create a new ERC-20 token with bonding curve
function createToken(TokenParams calldata tp, BondParams calldata bp) external payable returns (address);

/// @notice Transfer the creator role (royalty recipient) for a token
function updateBondCreator(address token, address creator) external;

/// @notice Mint tokens on the bonding curve
/// @return reserveAmount Amount of reserve token spent
function mint(address token, uint256 tokensToMint, uint256 maxReserveAmount, address receiver)
external
returns (uint256);

/// @notice Burn tokens on the bonding curve
/// @return refundAmount Amount of reserve token refunded
function burn(address token, uint256 tokensToBurn, uint256 minRefund, address receiver) external returns (uint256);

/// @notice Get the reserve amount required to mint tokens
function getReserveForToken(address token, uint256 tokensToMint)
external
view
returns (uint256 reserveAmount, uint256 royalty);

/// @notice Get the refund for burning tokens
function getRefundForTokens(address token, uint256 tokensToBurn)
external
view
returns (uint256 refundAmount, uint256 royalty);

/// @notice Claim accumulated royalties (inherited from MCV2_Royalty)
function claimRoyalties(address reserveToken) external;
}