This sample Solidity Smart Contract is for a funding pool. It allows for any address to contribute to the funding pool by sending ether directly to the contract. Addresses that have sent ether to the contract would then be eligible to vote. 1 wei = 1 vote. The address that receives the threshold amount of votes (10 ether) would be eligible to get the total balance of the pot.
- the funding pool is a smart contract
- allows anyone to contribute to the funding pool
- funding pool allows for distribution of funds
- funds are distributed wholly (total balance)
- funds are distributed to a single recipient
- the recipient is chosen via voting
- only contributors can vote
- only owner can distribute
- voting weights are proportionate to contributions made to the pool
- the contract owner can be trusted to only call distribute() after doing due dilligence on the to-be recipient
- this contract's design makes it a one use contract
- ownership is not transferrable in the current implementation
transfer
andsend
will not work since the receive() function requires more than 2300 gas as it calls_contribute
- there is a reliance on the contract owner to validate the
to
address fordistribute()
(that it has the highest number of votes and is a legitimate candidate) - this contract allows the contract owner to call
distribute()
for any address that has more than the threshold amount of votes
- Foundry (includes Forge, Cast, and Anvil)
- Git
- Clone the repository
git clone https://github.com/your-username/solidity-funding-pool.git
cd solidity-funding-pool
- Install dependencies
forge install
Compile the contracts:
forge build
View contract sizes:
forge build --sizes
Run all tests:
forge test
Run tests with verbose output:
forge test -vvv
Run a specific test:
forge test --match-test testFunctionName -vvv
- Set up your environment variables (Create a
.env
file):
PRIVATE_KEY=your_private_key
RPC_URL=your_rpc_url
- Deploy to a network:
source .env
forge script script/FundingPool.sol:FundingPoolScript --rpc-url https://optimism-sepolia.gateway.tenderly.co --account default --sender <SENDER_ADDRESS> --broadcast
After deployment, you can interact with the contract using Cast:
- Contribute funds:
cast send <CONTRACT_ADDRESS> --value <AMOUNT_IN_ETH>ether --private-key $PRIVATE_KEY
- Vote for a recipient:
cast send <CONTRACT_ADDRESS> "vote(address,uint256)" <RECIPIENT_ADDRESS> <VOTES_TO_CAST> --private-key $PRIVATE_KEY
- Distribute funds (owner only):
cast send <CONTRACT_ADDRESS> "distribute(address)" <RECIPIENT_ADDRESS> --private-key $PRIVATE_KEY
- Check contributions:
cast call <CONTRACT_ADDRESS> "contributions(address)" <CONTRIBUTOR_ADDRESS>
- Check votes received:
cast call <CONTRACT_ADDRESS> "votesReceived(address)" <RECIPIENT_ADDRESS>
- Start a local Ethereum node:
anvil
- Deploy to local node:
forge script script/FundingPool.sol:FundingPoolScript --rpc-url http://localhost:8545 --private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 --broadcast
The private key above is Anvil's default first account private key.
Generate test coverage report:
forge coverage
Generate gas usage report:
forge test --gas-report