Skip to content

oak-network/safe-multisig-helper-contracts

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

28 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Safe Multisig Helper Contracts

A comprehensive adapter system for managing treasury contracts through Safe multisig wallets, with support for meta-transactions to preserve caller identity.

Tests Solidity

Overview

The AdapterManager contract enables Safe multisig wallets to efficiently manage multiple treasury contracts through a unified interface. It combines three specialized adapters into a single contract and implements a meta-transaction pattern to preserve the original caller's identity.

Why This Helper Contract?

Managing multiple treasury contracts with a Safe multisig wallet creates operational bottlenecks:

  • ❌ Each treasury requires separate role permissions
  • ❌ Every permission change needs meeting the Safe's signature threshold
  • ❌ Managing permissions across multiple treasuries is exponentially complex
  • ❌ Each treasury update requires a full Safe transaction with multiple signatures

AdapterManager solves this by:

βœ… Consolidating permissions - Configure Safe permission once for the AdapterManager
βœ… Eliminating repetitive signatures - Manage all treasury interactions through one contract
βœ… Standardized interface - Consistent API for all treasury operations
βœ… Meta-transaction support - Preserves original caller identity for access control
βœ… Quick treasury additions - Add new treasuries without Safe permission changes

Key Features

🎯 Unified Adapter System

  • AllOrNothingAdapter - Cancel, pause, unpause operations
  • KeepWhatsRaisedAdapter - Crowdfunding treasury management (13 functions)
  • PaymentTreasuryAdapter - Payment processing operations (9 functions)

πŸ”„ Meta-Transaction Pattern

  • Preserves Safe multisig identity when calling treasury contracts
  • Treasury contracts can verify the actual caller (not just the adapter)
  • Enables proper access control and audit trails
  • ~200-300 gas overhead per transaction

πŸ”’ Security

  • Simple admin-based access control
  • Zero-address validation on all functions
  • Custom error handling for gas efficiency
  • Non-upgradeable design for simplicity

πŸ› οΈ Flexibility

  • Generic executeCall() for any contract interaction
  • Support for complex data types (structs, arrays)
  • Overloaded function support
  • Batch operations

Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Safe Multisig  β”‚ (Admin)
β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚
         β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚       AdapterManager                β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚ KeepWhatsRaisedAdapter       β”‚  β”‚
β”‚  β”‚ AllOrNothingAdapter          β”‚  β”‚
β”‚  β”‚ PaymentTreasuryAdapter       β”‚  β”‚
β”‚  β”‚ BaseAdminAdapter             β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚ (with meta-transaction)
         β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Treasury        β”‚
β”‚ Contracts       β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Quick Start

Prerequisites

  • Node.js >=18.0
  • npm package manager

Installation

# Clone the repository
git clone https://github.com/ccprotocol/safe-multisig-helper-contracts.git
cd safe-multisig-helper-contracts

# Install dependencies
npm install

# Compile contracts
npm run compile

2. Install dependencies

# 1. Install dependencies
npm install

3. Set env

1. npx hardhat vars set PRIVATE_KEY
2. npx hardhat vars set SAFE_ADMIN

For more : configuration-variables

Testing

# Run all tests (52 tests)
npm test

# Run with gas reporting
npm run test:gas

# Run with coverage
npm run test:coverage

Deployment

# Deploy to Alfajores testnet
npm run deploy:alfajores

# Deploy to Celo mainnet
npm run deploy:celo

# Deploy with custom Safe multisig as admin
npx hardhat ignition deploy ignition/modules/deploy.ts \
  --network alfajores \
  --parameters '{"DeployAdapterManager":{"adminAddress":"0xYourSafeAddress"}}'

Documentation

πŸ“š Core Documentation

Document Description
docs/DEPLOYMENT.md Comprehensive deployment guide with examples, verification, and troubleshooting
docs/META_TRANSACTIONS.md Complete guide to the meta-transaction pattern implementation

πŸš€ Deployment & Testing

Document Description
ignition/README.md Hardhat Ignition deployment guide and quick reference
test/README.md Test suite documentation and usage

πŸ“– Additional Resources

Contract Functions

AllOrNothingAdapter (3 functions)

aonCancelTreasury(address treasury, bytes32 message)
aonPauseTreasury(address treasury, bytes32 message)
aonUnpauseTreasury(address treasury, bytes32 message)

KeepWhatsRaisedAdapter (13 functions)

setPaymentGatewayFee(address treasury, bytes32 pledgeId, uint256 fee)
approveWithdrawal(address treasury)
configureTreasury(address treasury, ...)
updateDeadline(address treasury, uint256 deadline)
updateGoalAmount(address treasury, uint256 goalAmount)
setFeeAndPledge(address treasury, ...)
withdraw(address treasury, uint256 amount)
claimTip(address treasury)
claimFund(address treasury)
kwrCancelTreasury(address treasury, bytes32 message)
kwrPauseTreasury(address treasury, bytes32 message)
kwrUnpauseTreasury(address treasury, bytes32 message)

PaymentTreasuryAdapter (9 functions)

createPayment(address treasury, ...)
cancelPayment(address treasury, bytes32 paymentId)
confirmPayment(address treasury, bytes32 paymentId)
confirmPaymentBatch(address treasury, bytes32[] paymentIds)
claimRefund(address treasury, bytes32 paymentId)
claimRefund(address treasury, bytes32 paymentId, address refundAddress)
ptCancelTreasury(address treasury, bytes32 message)
ptPauseTreasury(address treasury, bytes32 message)
ptUnpauseTreasury(address treasury, bytes32 message)

BaseAdminAdapter

changeAdmin(address _newAdmin)
executeCall(address target, bytes calldata data) returns (bool, bytes)

Meta-Transaction Pattern

All adapter functions append the caller's address to the calldata, allowing treasury contracts to extract and verify the original Safe multisig address:

// In AdapterManager
bytes memory dataWithSender = abi.encodePacked(data, msg.sender);
treasury.call(dataWithSender);

// In Treasury Contract
function _msgSender() internal view returns (address) {
    if (msg.data.length >= 20) {
        assembly {
            sender := shr(96, calldataload(sub(calldatasize(), 20)))
        }
    } else {
        return msg.sender;
    }
}

See docs/META_TRANSACTIONS.md for complete implementation details.

Testing

The project includes comprehensive test coverage:

  • βœ… 52 tests passing
  • βœ… AdapterManager tests - Deployment, access control, inheritance
  • βœ… Meta-transaction tests - Sender extraction, complex scenarios
  • βœ… Adapter tests - All functions for each adapter type
  • βœ… Mock contracts - Treasury implementations for testing

Run tests:

4. Compile the contracts

# Testnet
npm run deploy:alfajores

# Mainnet
npm run deploy:celo

Verification

After deployment, verify on Celoscan:

npx hardhat verify --network alfajores <CONTRACT_ADDRESS> "<ADMIN_ADDRESS>"

Post-Deployment

  1. Save the deployed contract address
  2. Verify the contract on Celoscan
  3. Test admin functions
  4. Transfer admin to Safe multisig if needed
  5. Document for multisig-permission-kit

See docs/DEPLOYMENT.md for detailed deployment instructions.

Project Structure

safe-multisig-helper-contracts/
β”œβ”€β”€ contracts/
β”‚   β”œβ”€β”€ AdapterManager.sol              # Main contract
β”‚   β”œβ”€β”€ base/
β”‚   β”‚   └── BaseAdminAdapter.sol        # Base admin functionality
β”‚   β”œβ”€β”€ AllOrNothingAdapter.sol         # AoN treasury adapter
β”‚   β”œβ”€β”€ KeepWhatsRaisedAdapter.sol      # KWR treasury adapter
β”‚   β”œβ”€β”€ PaymentTreasuryAdapter.sol      # Payment treasury adapter
β”‚   β”œβ”€β”€ interfaces/                     # Treasury interfaces
β”‚   └── mocks/                          # Mock contracts for testing
β”œβ”€β”€ test/
β”‚   β”œβ”€β”€ AdapterManager.test.ts          # Main contract tests
β”‚   β”œβ”€β”€ MetaTransaction.test.ts         # Meta-transaction tests
β”‚   β”œβ”€β”€ AllOrNothingAdapter.test.ts     # AoN adapter tests
β”‚   β”œβ”€β”€ KeepWhatsRaisedAdapter.test.ts  # KWR adapter tests
β”‚   β”œβ”€β”€ PaymentTreasuryAdapter.test.ts  # Payment adapter tests
β”‚   └── README.md                       # Test documentation
β”œβ”€β”€ ignition/
β”‚   β”œβ”€β”€ modules/
β”‚   β”‚   └── deploy.ts                   # Deployment module
β”‚   β”œβ”€β”€ parameters.json                 # Deployment parameters
β”‚  
β”œβ”€β”€ docs/
β”‚   β”œβ”€β”€ DEPLOYMENT.md                   # Deployment documentation
β”‚   β”œβ”€β”€ META_TRANSACTIONS.md            # Meta-transaction guide
β”œβ”€β”€ hardhat.config.ts                   # Hardhat configuration
└── package.json                        # Dependencies and scripts

5. Future Use

Save the contract address for multisig-permission-kit

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published