Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
ba4e65d
Add Polygon Amoy
rayedsikder Jan 22, 2025
3ef8353
Added _pledge as a reusable utility
rayedsikder Jan 22, 2025
c5b6d82
Add function to add rewards in batch
rayedsikder Jan 23, 2025
13d9d74
Add function to add items in batch
rayedsikder Jan 23, 2025
305129f
Add Openzeppelin library
rayedsikder Apr 18, 2025
21bf78c
Update .env example
rayedsikder Apr 18, 2025
2946df8
Update foundry configs
rayedsikder Apr 18, 2025
e35053f
Remove hardhat deps
rayedsikder Apr 18, 2025
06ecd96
Remove hardhat scripts
rayedsikder Apr 18, 2025
420f331
Update mock token type
rayedsikder Apr 18, 2025
2ac7476
Add IReward for managing Reward struct
rayedsikder Apr 18, 2025
5b5d5cd
Update pragma and rename `platformBytes` to `platformHash`
rayedsikder Apr 18, 2025
9985e31
Add ability to cancel a campaign
rayedsikder Apr 18, 2025
c63ac47
Add pause, cancel functions; add initializer's
rayedsikder Apr 18, 2025
e10bf74
Refactor GlobalParams
rayedsikder Apr 18, 2025
75f506a
Update TreasuryFactory interface
rayedsikder Apr 18, 2025
a85d78b
Upgrade treasury deployment method
rayedsikder Apr 18, 2025
e82b91c
Remove Pausible import from Global params
rayedsikder Apr 18, 2025
26ff023
Add counters in utils
rayedsikder Apr 18, 2025
74b28d6
Refactor CampaignAccessChecker to make compatible with ERC1167 proxy …
rayedsikder Apr 18, 2025
375206a
Update Pragma version
rayedsikder Apr 18, 2025
d5fec59
Configure ERC1167 proxy deployment for CampaignInfo
rayedsikder Apr 18, 2025
796fb21
Remove unnecessary treasury models
rayedsikder Apr 18, 2025
45e8427
Update function names
rayedsikder Apr 18, 2025
06d120b
Remove dependency tests
rayedsikder Apr 18, 2025
16e2d85
Remove old scripts
rayedsikder Apr 18, 2025
0c48f66
Refactor BaseTreasury with Initializers and modify fee disbursement m…
rayedsikder Apr 18, 2025
9fe66ee
Upgrade AllOrNothing
rayedsikder Apr 18, 2025
c8caa61
Add log decoder utility functions
rayedsikder Apr 18, 2025
e4ec275
Update default values for test
rayedsikder Apr 18, 2025
c64daa2
Add unit test for TreasuryFactory
rayedsikder Apr 18, 2025
9ff397e
Update test for mock token
rayedsikder Apr 18, 2025
b467ac0
Add unit test for GlobalParams
rayedsikder Apr 18, 2025
153da0e
Add unit tests for CampaignInfoFactory
rayedsikder Apr 18, 2025
b221ccb
Update Base test configurations
rayedsikder Apr 18, 2025
56c0420
Upgrade test helper for reusing in all tests
rayedsikder Apr 18, 2025
90294af
Add integration test for AllOrNothing
rayedsikder Apr 18, 2025
546f816
Add base deployment functions
rayedsikder Apr 18, 2025
f576381
Add deployment script for TreasuryFactory
rayedsikder Apr 18, 2025
eec1f4a
Add deployment script for CampaignInfoFactory
rayedsikder Apr 18, 2025
2b60511
Add deployment script for GlobalParams
rayedsikder Apr 18, 2025
386fbb1
Add deployment script for mock token
rayedsikder Apr 18, 2025
b3b1ed2
Add full deployment script
rayedsikder Apr 18, 2025
2e6be44
Update docs
rayedsikder Apr 18, 2025
9079b46
Update readme.md
rayedsikder Apr 18, 2025
9bb367c
Update readme.md
rayedsikder Apr 18, 2025
f097e56
Add validations, initializer modifer and function for updating Campai…
rayedsikder Apr 22, 2025
c8376de
Update config constants and dependant functions
rayedsikder Apr 22, 2025
9bfa359
Fix issue validations
rayedsikder Apr 22, 2025
bffb989
Add custom errors, remove unused imports
rayedsikder Apr 22, 2025
268ea1b
Update Interface
rayedsikder Apr 22, 2025
029331f
Remove unnecessary contract
rayedsikder Apr 22, 2025
5d9b7f7
Improve validation logic, remove redundant functions
rayedsikder Apr 22, 2025
aaf5363
Update function names to make it consistent with its logic
rayedsikder Apr 22, 2025
81cf732
Remove `addReward` helper function, and update tests for `addRewards`
rayedsikder Apr 22, 2025
13013cc
Fix issue with `claimRefund`
rayedsikder Apr 22, 2025
7f02f34
Remove console.sol import
rayedsikder Apr 22, 2025
b25b0ca
Add validation to prevent setting zero address as campaignInfo implem…
rayedsikder Apr 22, 2025
bfb33b0
Update comment
rayedsikder Apr 22, 2025
0992b2a
Add custom errors instead of require statements
rayedsikder Apr 22, 2025
fbe1ec9
Update workflow and remove npm runs
rayedsikder Apr 22, 2025
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
17 changes: 13 additions & 4 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,6 @@ env:

jobs:
check:
strategy:
fail-fast: true

name: Foundry project
runs-on: ubuntu-latest
steps:
Expand All @@ -34,7 +31,6 @@ jobs:

- name: Run Forge build
run: |
npm ci
forge --version
forge build --sizes
id: build
Expand All @@ -43,3 +39,16 @@ jobs:
run: |
forge test -vvv
id: test

- name: Run gas report
run: |
forge test --gas-report > gas-report.txt
if: always()
id: gas

- name: Archive gas report
uses: actions/upload-artifact@v3
if: always()
with:
name: gas-report
path: gas-report.txt
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
[submodule "lib/forge-std"]
path = lib/forge-std
url = https://github.com/foundry-rs/forge-std
[submodule "lib/openzeppelin-contracts"]
path = lib/openzeppelin-contracts
url = https://github.com/OpenZeppelin/openzeppelin-contracts
153 changes: 113 additions & 40 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,67 +1,140 @@
# CCP Contracts
This repository contains the smart contracts source code and campaign configuration for Creative Crowdfunding Protocol - CCP. The repository uses Foundry as development environment for compilation, testing and deployment tasks.
# Creative Crowdfunding Protocol (CC Protocol) Smart Contracts

## What is CCP?
CCP is a protocol for crowdfunding campaigns that allows creators to multilist campaigns across different crowdfunding platforms. It provides infrastructure tooling and support for platforms to create and manage campaigns in web3.
## Overview

## Documentation
The detailed technical documentation for the protocol can be found in the [docs](./docs/src/SUMMARY.md) folder.
CC Protocol is a decentralized crowdfunding protocol designed to help creators launch and manage campaigns across multiple platforms. By providing a standardized infrastructure, the protocol simplifies the process of creating, funding, and managing crowdfunding initiatives in web3 across different platforms.

## Features

- Cross-listable campaign creation
- Multiple treasury models
- Secure fund management
- Customizable protocol parameters

## Prerequisites

## Getting Started
### Prerequisites
The following tools are required to be installed in your system:
- [Foundry](https://book.getfoundry.sh/getting-started/installation)
- [Node.js](https://nodejs.org/en/download/)
- [Foundry](https://book.getfoundry.sh/)
- Solidity ^0.8.20
- Node.js (recommended)

### Installation
## Installation

```shell
$ npm install
1. Clone the repository:

```bash
git clone https://github.com/ccprotocol/ccprotocol-contracts.git
cd ccprotocol-contracts
```

### Build
2. Install dependencies:

```shell
$ forge build
```bash
forge install
```

### Test
3. Copy environment template:

```shell
$ forge test
```bash
cp .env.example .env
```

### Format
4. Configure your `.env` file with:

- Private key
- RPC URL
- (Optional) Contract addresses for reuse

## Documentation

Comprehensive documentation is available in the `docs/` folder:

- Technical specifications
- Contract interfaces
- Deployment guides
- Development setup instructions

To view the documentation:

```bash
# Navigate to docs folder
cd docs
```

## Development

### Compile Contracts

```shell
$ forge fmt
```bash
forge build
```

### Gas Snapshots
### Run Tests

```shell
$ forge snapshot
```bash
# Run all tests
forge test

# Run specific test
forge test --match-test testFunctionName

# Run tests with more verbose output
forge test -vvv
```

## Deploy
### Environment Variables
### Deploy Contracts

Create an environment file named `.env`, fill the environment variables following the `.env.example` file and source the file using the following command:
#### Local Deployment

```shell
$ source .env
```bash
# Start local blockchain
anvil

# Deploy to local network
forge script script/DeployAll.s.sol:DeployAll --rpc-url http://localhost:8545 --private-key $PRIVATE_KEY --broadcast
```

### Local Deployment
To deploy the contracts locally, run the following command:
#### Testnet Deployment

```shell
$ forge script script/Setup.s.sol:SetupScript
```bash
# Deploy to testnet
forge script script/DeployAll.s.sol:DeployAll --rpc-url $RPC_URL --private-key $PRIVATE_KEY --broadcast -vvvv
```

### Remote Deployment
To deploy the contracts to a remote network, run the following command:
## Contract Architecture

### Core Contracts

- `TestUSD`: Mock ERC20 token for testing
- `GlobalParams`: Protocol-wide parameter management
- `CampaignInfoFactory`: Campaign creation and management
- `TreasuryFactory`: Treasury contract deployment

### Treasury Models

- `AllOrNothing`: Funds refunded if campaign goal not met

## Deployment Workflow

1. Deploy `TestUSD`
2. Deploy `GlobalParams`
3. Deploy `TreasuryFactory`
4. Deploy `CampaignInfoFactory`

## Environment Variables

Key environment variables in `.env`:

- `PRIVATE_KEY`: Deployment wallet private key
- `RPC_URL`: Network RPC endpoint
- `SIMULATE`: Toggle simulation mode
- Contract address variables for reuse

## Troubleshooting

- Ensure sufficient network gas tokens
- Verify RPC URL connectivity
- Check contract dependencies

## License

```shell
$ forge script script/Setup.s.sol:SetupScript --rpc-url $RPC_URL --private-key $PRIVATE_KEY
```
[SPDX-License-Identifier: UNLICENSED]
1 change: 1 addition & 0 deletions docs/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
book/
13 changes: 13 additions & 0 deletions docs/book.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
table {
margin: 0 auto;
border-collapse: collapse;
width: 100%;
}

table td:first-child {
width: 15%;
}

table td:nth-child(2) {
width: 25%;
}
13 changes: 13 additions & 0 deletions docs/book.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[book]
src = "src"
title = ""

[output.html]
no-section-label = true
additional-js = ["solidity.min.js"]
additional-css = ["book.css"]
mathjax-support = true
git-repository-url = "https://github.com/ccprotocol/reference-client-sc"

[output.html.fold]
enable = true
74 changes: 74 additions & 0 deletions docs/solidity.min.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
hljs.registerLanguage("solidity",(()=>{"use strict";function e(){try{return!0
}catch(e){return!1}}
var a=/-?(\b0[xX]([a-fA-F0-9]_?)*[a-fA-F0-9]|(\b[1-9](_?\d)*(\.((\d_?)*\d)?)?|\.\d(_?\d)*)([eE][-+]?\d(_?\d)*)?|\b0)(?!\w|\$)/
;e()&&(a=a.source.replace(/\\b/g,"(?<!\\$)\\b"));var s={className:"number",
begin:a,relevance:0},n={
keyword:"assembly let function if switch case default for leave break continue u256 jump jumpi stop return revert selfdestruct invalid",
built_in:"add sub mul div sdiv mod smod exp not lt gt slt sgt eq iszero and or xor byte shl shr sar addmod mulmod signextend keccak256 pc pop dup1 dup2 dup3 dup4 dup5 dup6 dup7 dup8 dup9 dup10 dup11 dup12 dup13 dup14 dup15 dup16 swap1 swap2 swap3 swap4 swap5 swap6 swap7 swap8 swap9 swap10 swap11 swap12 swap13 swap14 swap15 swap16 mload mstore mstore8 sload sstore msize gas address balance selfbalance caller callvalue calldataload calldatasize calldatacopy codesize codecopy extcodesize extcodecopy returndatasize returndatacopy extcodehash create create2 call callcode delegatecall staticcall log0 log1 log2 log3 log4 chainid origin gasprice basefee blockhash coinbase timestamp number difficulty gaslimit",
literal:"true false"},i={className:"string",
begin:/\bhex'(([0-9a-fA-F]{2}_?)*[0-9a-fA-F]{2})?'/},t={className:"string",
begin:/\bhex"(([0-9a-fA-F]{2}_?)*[0-9a-fA-F]{2})?"/};function r(e){
return e.inherit(e.APOS_STRING_MODE,{begin:/(\bunicode)?'/})}function l(e){
return e.inherit(e.QUOTE_STRING_MODE,{begin:/(\bunicode)?"/})}var o={
SOL_ASSEMBLY_KEYWORDS:n,baseAssembly:e=>{
var a=r(e),o=l(e),c=/[A-Za-z_$][A-Za-z_$0-9.]*/,d=e.inherit(e.TITLE_MODE,{
begin:/[A-Za-z$_][0-9A-Za-z$_]*/,lexemes:c,keywords:n}),u={className:"params",
begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,lexemes:c,keywords:n,
contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,a,o,s]},_={
className:"operator",begin:/:=|->/};return{keywords:n,lexemes:c,
contains:[a,o,i,t,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,s,_,{
className:"function",lexemes:c,beginKeywords:"function",end:"{",excludeEnd:!0,
contains:[d,u,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,_]}]}},
solAposStringMode:r,solQuoteStringMode:l,HEX_APOS_STRING_MODE:i,
HEX_QUOTE_STRING_MODE:t,SOL_NUMBER:s,isNegativeLookbehindAvailable:e}
;const{baseAssembly:c,solAposStringMode:d,solQuoteStringMode:u,HEX_APOS_STRING_MODE:_,HEX_QUOTE_STRING_MODE:m,SOL_NUMBER:b,isNegativeLookbehindAvailable:E}=o
;return e=>{for(var a=d(e),s=u(e),n=[],i=0;i<32;i++)n[i]=i+1
;var t=n.map((e=>8*e)),r=[];for(i=0;i<=80;i++)r[i]=i
;var l=n.map((e=>"bytes"+e)).join(" ")+" ",o=t.map((e=>"uint"+e)).join(" ")+" ",g=t.map((e=>"int"+e)).join(" ")+" ",M=[].concat.apply([],t.map((e=>r.map((a=>e+"x"+a))))),p={
keyword:"var bool string int uint "+g+o+"byte bytes "+l+"fixed ufixed "+M.map((e=>"fixed"+e)).join(" ")+" "+M.map((e=>"ufixed"+e)).join(" ")+" enum struct mapping address new delete if else for while continue break return throw emit try catch revert unchecked _ function modifier event constructor fallback receive error virtual override constant immutable anonymous indexed storage memory calldata external public internal payable pure view private returns import from as using pragma contract interface library is abstract type assembly",
literal:"true false wei gwei szabo finney ether seconds minutes hours days weeks years",
built_in:"self this super selfdestruct suicide now msg block tx abi blockhash gasleft assert require Error Panic sha3 sha256 keccak256 ripemd160 ecrecover addmod mulmod log0 log1 log2 log3 log4"
},O={className:"operator",begin:/[+\-!~*\/%<>&^|=]/
},C=/[A-Za-z_$][A-Za-z_$0-9]*/,N={className:"params",begin:/\(/,end:/\)/,
excludeBegin:!0,excludeEnd:!0,lexemes:C,keywords:p,
contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,a,s,b,"self"]},f={
begin:/\.\s*/,end:/[^A-Za-z0-9$_\.]/,excludeBegin:!0,excludeEnd:!0,keywords:{
built_in:"gas value selector address length push pop send transfer call callcode delegatecall staticcall balance code codehash wrap unwrap name creationCode runtimeCode interfaceId min max"
},relevance:2},y=e.inherit(e.TITLE_MODE,{begin:/[A-Za-z$_][0-9A-Za-z$_]*/,
lexemes:C,keywords:p}),w={className:"built_in",
begin:(E()?"(?<!\\$)\\b":"\\b")+"(gas|value|salt)(?=:)"};function x(e,a){return{
begin:(E()?"(?<!\\$)\\b":"\\b")+e+"\\.\\s*",end:/[^A-Za-z0-9$_\.]/,
excludeBegin:!1,excludeEnd:!0,lexemes:C,keywords:{built_in:e+" "+a},
contains:[f],relevance:10}}var h=c(e),v=e.inherit(h,{
contains:h.contains.concat([{begin:/\./,end:/[^A-Za-z0-9$.]/,excludeBegin:!0,
excludeEnd:!0,keywords:{built_in:"slot offset length address selector"},
relevance:2},{begin:/_/,end:/[^A-Za-z0-9$.]/,excludeBegin:!0,excludeEnd:!0,
keywords:{built_in:"slot offset"},relevance:2}])});return{aliases:["sol"],
keywords:p,lexemes:C,
contains:[a,s,_,m,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,b,w,O,{
className:"function",lexemes:C,
beginKeywords:"function modifier event constructor fallback receive error",
end:/[{;]/,excludeEnd:!0,
contains:[y,N,w,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE],illegal:/%/
},x("msg","gas value data sender sig"),x("block","blockhash coinbase difficulty gaslimit basefee number timestamp chainid"),x("tx","gasprice origin"),x("abi","decode encode encodePacked encodeWithSelector encodeWithSignature encodeCall"),x("bytes","concat"),f,{
className:"class",lexemes:C,beginKeywords:"contract interface library",end:"{",
excludeEnd:!0,illegal:/[:"\[\]]/,contains:[{beginKeywords:"is",lexemes:C
},y,N,w,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{lexemes:C,
beginKeywords:"struct enum",end:"{",excludeEnd:!0,illegal:/[:"\[\]]/,
contains:[y,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{
beginKeywords:"import",end:";",lexemes:C,keywords:"import from as",
contains:[y,a,s,_,m,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,O]},{
beginKeywords:"using",end:";",lexemes:C,keywords:"using for",
contains:[y,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,O]},{className:"meta",
beginKeywords:"pragma",end:";",lexemes:C,keywords:{
keyword:"pragma solidity experimental abicoder",
built_in:"ABIEncoderV2 SMTChecker v1 v2"},
contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,e.inherit(a,{
className:"meta-string"}),e.inherit(s,{className:"meta-string"})]},{
beginKeywords:"assembly",end:/\b\B/,
contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,e.inherit(v,{begin:"{",
end:"}",endsParent:!0,contains:v.contains.concat([e.inherit(v,{begin:"{",
end:"}",contains:v.contains.concat(["self"])})])})]}],illegal:/#/}}})());

// Ugly hack to reload HLJS
hljs.initHighlightingOnLoad();
Loading
Loading