Endorsable provides a comprehensive, inheritable smart contract framework for managing and tracking on-chain endorsements. The system offers two complementary contracts:
Endorsable.sol: Contract-level endorsements for entire smart contractsEndorsableState.sol: State-specific endorsements for individual components within contracts
By extending these contracts, any smart contract can implement robust endorsement systems with clear lifecycle management, making them ideal for trust, verification, and reputation scenarios in decentralized applications.
- π Owner-Controlled Requests: Contract owner manages endorsement requests
- β Endorsement Granting: Requested addresses can provide endorsements
- π Revocation Support: Endorsers can revoke their endorsements
- ποΈ Owner Removal: Contract owner can remove any endorsement
- π¬ Comment System: All actions support contextual comments (emitted in events)
- π Access Control: Built on OpenZeppelin's
Ownablefor security
- π― Granular Endorsements: Endorse specific states/components within contracts
- π Dual System: Inherits contract-level endorsements + adds state-specific functionality
- π¦ Batch Operations: Efficient batch requests and status checks
- π·οΈ Flexible Identifiers: Use string identifiers for different states/projects
- π Independent Tracking: Each state maintains separate endorsement status
- π Comprehensive Queries: Query endorsements at both contract and state levels
- π‘οΈ Security: Comprehensive access controls and state validation
- π Event Logging: Complete audit trail through event emissions
- β‘ Gas Efficient: Optimized for minimal gas consumption
- π§ͺ Battle-Tested: Comprehensive test coverage with edge case handling
- π Well-Documented: Extensive documentation and examplesIT)
EndorsableState.sol: Brand new contract enabling state-specific endorsements within a single contract- Dual Endorsement System: Support for both contract-level and granular state-level endorsements
- Enhanced Examples: Comprehensive real-world examples with
ReputableBusinessandProjectPortfolio - Batch Operations: Efficient batch endorsement requests and status checks
- Improved Interface Design: Cleaner, more intuitive API with enhanced documentation
- State Management: Each endorsable state maintains independent endorsement tracking
- Better Constructor Design: Streamlined initialization with initial endorsement requests
- Enhanced Testing: Comprehensive test suites covering edge cases and integration scenarios
- Documentation Overhaul: Complete rewrite with detailed usage guides and best practices
- Gas Optimization: More efficient batch operations for multiple address operations
- Fixed state transition edge cases in endorsement lifecycle
- Improved error messaging for better debugging
- Enhanced access control validationle
A 'micro-contract' experiment - the smallest utility contract that can offer real-world benefits.
Endorsable provides an inheritable, structured mechanism for managing and tracking endorsements of a contract on-chain.
By extending Endorsable, any parent contract can allow external addresses (EOAs or other contracts) to grant endorsements on itself.
The contract enforces a clear endorsement lifecycle of requests, approvals, revocations, and removals, making it ideal for scenarios where trust, verification, and reputation are important.
| Contract | Purpose | Inheritance | Use Case |
|---|---|---|---|
Endorsable.sol |
Contract-level endorsements | Ownable |
Business reputation, service certification |
EndorsableState.sol |
State-specific endorsements | Endorsable |
Project portfolios, feature validation |
Both contracts use a standardized 5-state endorsement lifecycle:
UNASSIGNED (0) β REQUESTED (1) β ENDORSED (2)
β β
REMOVED (4) REVOKED (3)
UNASSIGNED (0): No endorsement interaction has occurredREQUESTED (1): Contract owner has requested an endorsementENDORSED (2): Address has provided an endorsementREVOKED (3): Endorser has revoked their endorsementREMOVED (4): Contract owner has removed the endorsement
-
Smart Contract Security Audits & Certifications
- Security audit firms endorse verified smart contracts
- Endorsements can be revoked if vulnerabilities are discovered
- DeFi protocols display audit endorsements to users
-
DAO Governance & Reputation Systems
- DAOs require endorsements before executing governance actions
- Member reputation tracking and voting weight determination
- Multi-signature endorsement requirements for critical decisions
-
Service Provider Verification
- Professional service providers (lawyers, consultants, developers)
- Business partnership and vendor verification systems
- Regulatory compliance and certification tracking
-
Project Portfolio Management
- Freelancers showcase endorsed individual projects
- Software development milestone validation
- Creative work and portfolio piece endorsements
-
Feature-Specific Validation
- Individual smart contract features endorsed separately
- API endpoint validation and certification
- Module-level security assessments
-
Academic & Research Applications
- Peer review systems for research projects
- Individual publication endorsements
- Course and curriculum component validation
- Standardized Endorsement Workflow: Any subscribing contract can be endorsed by any other contracts or EOAs (only if requested).
- Trust & Reputation Management: Useful in permissioned environments like DAOs, audits, and credentialing.
- Security & Transparency: The contract is designed to be as simplea & clear as possible. It is also built with OpenZeppelinβs
Ownablecontract for uncomplicated access control. (TODO: considerownership2stepextension )
- Endorsement Requests: The contract owner can request an endorsement for another smart contract.
- Endorsement Granting: A requested contract/account can grant endorsement.
- Revoking Endorsement: Contracts can revoke their endorsement.
- Removing Endorsements: The owner can remove an endorsement.
- Simplified Permission Control: Uses OpenZeppelinβs
Ownablefor simple access control (possibly loking at usingOwnable2stepextension) - Comment on any action (v0.0.2-beta): All functions now include a comment parameter, enabling endorsers, revokers, or the contract owner to add contextual information with each action. This comment is not stored on-chain; instead, it is emitted in the corresponding event. It can be any stringβfor instance, a link to a supporting document on IPFS or a brief explanation for endorsing, revoking, or removing an endorsement.
Option 1: Foundry (Recommended)
forge install https://github.com/brucedonovan/endorsable.gitOption 2: NPM/Yarn
npm install @brucedonovan/endorsable
# or
yarn add @brucedonovan/endorsablepragma solidity ^0.8.13;
import "@brucedonovan/endorsable/src/Endorsable.sol";
contract MyContract is Endorsable {
constructor(address[] memory _initialRequests)
Endorsable(_initialRequests)
{
// Your contract logic
}
// Your contract functions...
}pragma solidity ^0.8.13;
import "@brucedonovan/endorsable/src/EndorsableState.sol";
contract MyProjectPortfolio is EndorsableState {
constructor(address[] memory _initialRequests)
EndorsableState(_initialRequests)
{
// Your contract logic
}
function createProject(string memory projectId) external onlyOwner {
// Create project logic...
// Request endorsements for this specific project
address[] memory endorsers = [reviewer1, client1, auditor1];
for (uint i = 0; i < endorsers.length; i++) {
requestStateEndorsement(projectId, endorsers[i], "Please review this project");
}
}
}- New Contract:
EndorsableState.solfor state-specific endorsements - Dual Endorsement System: Support for both contract-level and state-level endorsements
- Enhanced Examples: Added
ReputableBusiness.solandProjectPortfolio.solexamples - Batch Operations: Efficient batch endorsement requests and status queries
- Improved Architecture: Better separation of concerns between contract types
- Constructor Enhancement: Streamlined initialization with initial endorsement requests
- Gas Optimization: More efficient batch operations for multiple address checks
- Enhanced Testing: Comprehensive test suites with 11+ tests per contract
- Documentation Overhaul: Complete rewrite with detailed guides and best practices
- Interface Design: Cleaner, more intuitive API with enhanced type safety
- Fixed state transition edge cases in endorsement lifecycle
- Improved error messaging for better debugging experience
- Enhanced access control validation for security
- Comment System: Added comment parameter to all functions for contextual information
- Event Enhancement: Comments included in all endorsement events
- Basic Endorsement Lifecycle: Request, endorse, revoke, remove functionality
- Owner Access Control: Built on OpenZeppelin's
Ownablecontract
- Foundry: Modern Solidity development framework
curl -L https://foundry.paradigm.xyz | bash foundryup
git clone https://github.com/brucedonovan/endorsable.git
cd endorsable
forge install# Run all tests
forge test
# Run with verbosity
forge test -vvv
# Run specific contract tests
forge test --match-contract EndorsableTest
forge test --match-contract EndorsableStateTest
# Run example tests
cd examples && forge testforge buildThe examples/ directory contains comprehensive, production-ready examples demonstrating real-world usage of both contracts:
- Purpose: Business reputation management with contract-level endorsements
- Features: Reputation scoring, trustworthiness evaluation, partner endorsements
- Use Cases: Service providers, business partnerships, regulatory compliance
- Purpose: Project portfolio with state-specific endorsements
- Features: Individual project endorsements, batch operations, quality assessment
- Use Cases: Freelancer portfolios, software projects, academic research
# Run all example tests
cd examples && forge test
# Run specific examples
forge test --match-contract ReputableBusinessTest --match-path "examples/test/*.sol"
forge test --match-contract ProjectPortfolioTest --match-path "examples/test/*.sol"
# Test with detailed output
cd examples && forge test -vvvπ See the Examples README for comprehensive guides, integration patterns, and best practices.
enum State {
UNASSIGNED, // 0: No interaction
REQUESTED, // 1: Endorsement requested
ENDORSED, // 2: Successfully endorsed
REVOKED, // 3: Endorsement revoked
REMOVED // 4: Endorsement removed by owner
}// Request endorsement from an address
function requestEndorsement(address addr, string calldata comment) external onlyOwner;
// Endorse the contract (only if requested)
function endorse(string calldata comment) external;
// Revoke your endorsement
function revokeEndorsement(string calldata comment) external;
// Remove endorsement (owner only)
function removeEndorsement(address addr, string calldata comment) external onlyOwner;
// Check endorsement status
function getEndorsementStatus(address addr) external view returns (uint8);// Request state-specific endorsement
function requestStateEndorsement(string calldata identifier, address addr, string calldata comment) external onlyOwner;
// Endorse a specific state
function endorseState(address owner, string calldata identifier, string calldata comment) external;
// Revoke state endorsement
function revokeStateEndorsement(address owner, string calldata identifier, string calldata comment) external;
// Remove state endorsement
function removeStateEndorsement(string calldata identifier, address addr, string calldata comment) external onlyOwner;
// Check state endorsement status
function getStateEndorsementStatus(address owner, string calldata identifier, address addr) external view returns (uint8);- Owner-Only Functions: Endorsement requests and removals restricted to contract owner
- Endorser Validation: Only requested addresses can provide endorsements
- State Protection: Comprehensive validation prevents invalid state transitions
- Input Validation: Always validate state identifiers and addresses
- Event Monitoring: Use events for off-chain indexing and monitoring
- Gas Optimization: Utilize batch functions for multiple operations
- Reentrancy Safety: Built-in protection against reentrancy attacks
- Implement endorsement expiry mechanisms for time-sensitive use cases
- Consider multi-signature requirements for critical endorsements
- Use IPFS links in comments for detailed endorsement documentation
- Implement reputation decay for long-term reputation systems
We welcome contributions! Please follow these guidelines:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request