<div align="center">
# 🛡️ Gnosis Safe AllowlistGuard
### Custom Smart Contract Guard for Enhanced Safe Wallet Security
[](https://docs.soliditylang.org/)
[](https://hardhat.org/)
[](https://ethereum.org/)
[](https://opensource.org/licenses/MIT)
[🚀 Live Demo](#-deployed-contracts) • [📖 Documentation](#-how-it-works) • [🧪 Run Tests](#-quick-start) • [🤝 Contribute](#-contributing)
</div>
---
## 📋 Table of Contents
- [Overview](#-overview)
- [Features](#-features)
- [Deployed Contracts](#-deployed-contracts)
- [Quick Start](#-quick-start)
- [How It Works](#-how-it-works)
- [Architecture](#-architecture)
- [Security](#-security)
- [Use Cases](#-use-cases)
- [API Reference](#-api-reference)
- [Testing](#-testing)
- [Deployment](#-deployment)
- [Contributing](#-contributing)
- [License](#-license)
---
## 🌟 Overview
**AllowlistGuard** is a production-ready smart contract that extends [Gnosis Safe](https://safe.global/) (formerly Gnosis Safe) with allowlist-based transaction validation. By implementing the Guard interface, this contract ensures that Safe wallets can only send transactions to pre-approved addresses.
### The Problem
Traditional Safe wallets allow transactions to any address. While multi-signature requirements add security, there's no way to restrict *where* funds can go.
### The Solution
AllowlistGuard acts as a gatekeeper, validating every transaction before execution. Only addresses on the approved allowlist can receive funds, providing an additional layer of security for DAOs, treasuries, and institutional wallets.
---
## ✨ Features
<table>
<tr>
<td width="50%">
### 🔒 Security First
- ✅ Allowlist-based validation
- ✅ Owner-only controls
- ✅ Zero address protection
- ✅ Custom error handling
- ✅ Event emission for transparency
</td>
<td width="50%">
### ⚡ Developer Friendly
- ✅ Gas optimized
- ✅ Comprehensive tests
- ✅ ERC165 interface support
- ✅ Well-documented code
- ✅ Hardhat integration
</td>
</tr>
</table>
### Key Capabilities
| Feature | Description |
|---------|-------------|
| 🎯 **Allowlist Management** | Add or remove approved addresses dynamically |
| 📦 **Batch Operations** | Add multiple addresses in a single transaction |
| 🔐 **Access Control** | Only guard owner can modify the allowlist |
| 🚨 **Transaction Blocking** | Automatically revert unauthorized transactions |
| 📊 **Event Logging** | Track all allowlist changes and validations |
---
## 🚀 Deployed Contracts
### Sepolia Testnet (Verified)
| Contract | Address | Explorer |
|----------|---------|----------|
| **AllowlistGuard** | `0x78C7696272a0c30bd6b5173EB68d7f2c5bd2df55` | [View on Etherscan ↗](https://sepolia.etherscan.io/address/0x78C7696272a0c30bd6b5173EB68d7f2c5bd2df55) |
| **MockSafe** | `0xC0F64bc4Db7D5eDCC9388F517485D898Ecae4370` | [View on Etherscan ↗](https://sepolia.etherscan.io/address/0xC0F64bc4Db7D5eDCC9388F517485D898Ecae4370) |
<div align="center">
**🌐 Network:** Ethereum Sepolia Testnet
**⛽ Gas Optimized:** ~50k gas per allowlist addition
**✅ Verified:** Source code verified on Etherscan
</div>
---
## ⚡ Quick Start
### Prerequisites
```bash
Node.js >= v16
npm or yarn
Git# 1️⃣ Clone the repository
git clone https://github.com/YOUR-USERNAME/gnosis-safe-allowlist-guard.git
cd gnosis-safe-allowlist-guard
# 2️⃣ Install dependencies
npm install --legacy-peer-deps
# 3️⃣ Set up environment variables
cp .env.example .env
# Edit .env with your SEPOLIA_RPC_URL and PRIVATE_KEY
# 4️⃣ Compile contracts
npx hardhat compile
# 5️⃣ Run tests
npx hardhat testGuards are smart contracts that hook into Safe transaction execution:
┌─────────────────────────────────────────────────────┐
│ Safe Wallet │
│ │
│ 1. Transaction Proposed ───────────────────┐ │
│ │ │
│ 2. Signatures Collected ▼ │
│ ┌─────────────────┤
│ 3. Execute Transaction ──────────►│ Guard Contract │
│ │ │
│ ┌─────────────────────────────│ checkTransaction│
│ │ │ ↓ │
│ │ ✅ Allowlisted │ Validate │
│ │ Transaction Executes │ ↓ │
│ │ │ ✅ or ❌ │
│ │ ❌ Not Allowlisted └─────────────────┤
│ │ Transaction Reverts │
│ │ │
│ 4. Post-execution Check ◄────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────┘
// 1️⃣ Deploy the Guard
AllowlistGuard guard = new AllowlistGuard(
owner,
[approvedAddress1, approvedAddress2]
);
// 2️⃣ Set Guard on Safe
safe.setGuard(address(guard));
// 3️⃣ Add addresses to allowlist
guard.addToAllowlist(newAddress);
// 4️⃣ Transactions are now protected
safe.execTransaction(allowlistedAddr, ...); // ✅ Success
safe.execTransaction(randomAddr, ...); // ❌ RevertsAllowlistGuard
├── State Variables
│ ├── owner (address)
│ └── allowlist (mapping)
├── Events
│ ├── AddressAllowlisted
│ ├── AddressRemovedFromAllowlist
│ └── TransactionChecked
├── Errors
│ ├── NotOwner
│ ├── AddressNotAllowlisted
│ └── ZeroAddress
└── Functions
├── checkTransaction() // Guard hook (before execution)
├── checkAfterExecution() // Guard hook (after execution)
├── addToAllowlist() // Owner only
├── removeFromAllowlist() // Owner only
├── batchAddToAllowlist() // Owner only
├── isAllowlisted() // View
└── supportsInterface() // ERC165
| Technology | Version | Purpose |
|---|---|---|
| Solidity | 0.8.19 | Smart contract language |
| Hardhat | 2.22 | Development environment |
| Ethers.js | 6.13 | Ethereum library |
| Chai | 4.3 | Testing framework |
- ✅ Access Control: Only the guard owner can modify the allowlist
- ✅ Input Validation: Zero address checks prevent accidental burns
- ✅ Custom Errors: Gas-efficient error handling
- ✅ Event Emission: All state changes emit events for transparency
- ✅ Reentrancy Safe: No external calls in validation logic
✓ Use of custom errors for gas optimization
✓ Checks-Effects-Interactions pattern
✓ Access control with modifiers
✓ Explicit function visibility
✓ NatSpec documentation
✓ Event emission for state changesRestrict DAO funds to only flow to approved vendors, grants, and operational addresses.
Ensure company Safe only pays verified employee wallets.
Limit DeFi protocol interactions to audited, approved contracts.
Create time-bound or condition-based payment restrictions.
function checkTransaction(
address to,
uint256 value,
bytes memory data,
Operation operation,
...
) externalValidates transaction before execution. Reverts if to address is not allowlisted.
function addToAllowlist(address target) external onlyOwnerAdds an address to the allowlist.
Access: Owner only
Events: Emits AddressAllowlisted(address)
function batchAddToAllowlist(address[] calldata targets) external onlyOwnerAdds multiple addresses to the allowlist in one transaction.
function removeFromAllowlist(address target) external onlyOwnerRemoves an address from the allowlist.
function isAllowlisted(address target) external view returns (bool)Checks if an address is allowlisted.
# Run all tests
npx hardhat test
# Run with gas reporting
REPORT_GAS=true npx hardhat test
# Run coverage
npx hardhat coverageAllowlistGuard with Safe
Guard Deployment
✓ Should deploy with correct owner
✓ Should have initial allowlisted address
Guard Management
✓ Should allow owner to add address
✓ Should allow owner to remove address
✓ Should batch add addresses
Transaction Validation
✓ Should allow transaction to allowlisted address
✓ Should reject transaction to non-allowlisted address
8 passing (2s)
# Terminal 1: Start local blockchain
npx hardhat node
# Terminal 2: Deploy contracts
npx hardhat run scripts/deploy.js --network localhost# 1. Get testnet ETH from faucet
# Visit: https://sepoliafaucet.com/
# 2. Configure .env
SEPOLIA_RPC_URL=https://eth-sepolia.g.alchemy.com/v2/YOUR-KEY
PRIVATE_KEY=your-private-key-without-0x
# 3. Deploy
npx hardhat run scripts/deploy.js --network sepolia
# 4. Verify on Etherscan
npx hardhat verify --network sepolia DEPLOYED_ADDRESS "CONSTRUCTOR_ARGS"gnosis-safe-allowlist-guard/
├── contracts/
│ ├── AllowlistGuard.sol # Main Guard implementation
│ └── MockSafe.sol # Safe mock for testing
├── test/
│ └── AllowlistGuard.test.js # Comprehensive test suite
├── scripts/
│ └── deploy.js # Deployment script
├── hardhat.config.js # Hardhat configuration
├── package.json # Dependencies
├── README.md # Documentation
├── .env.example # Environment template
├── .gitignore # Git ignore rules
└── LICENSE # MIT License
Contributions are welcome! Please follow these steps:
- Fork the repository
- Create a feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
Riya Gupta
- Gnosis Safe - Safe smart account architecture
- OpenZeppelin - Security best practices
- Hardhat - Development environment
- Ethereum Community - Continuous innovation
https://sepolia.etherscan.io/address/0xEF8B74EA469E27F2367EA7392b2c3C53AEAE0Dce
```