privacy-scaling-explorations / excubiae

an on-chain flexible & modular framework for implementing custom gatekeepers.
MIT License
2 stars 0 forks source link

Make `check()` an independent smart contract #5

Open 0xjei opened 1 month ago

0xjei commented 1 month ago

There's a proposal for changing the _check() method to be an independent smart contract (Checker). We must understand the trade-offs mainly in reuse of gatekeepers, DX and gas consumption. This alternative is going to be executed on the ar/checker-contract branch.

0xjei commented 1 month ago

After some discussions & feedbacks and classic trial-and-error approach, the drafty new core structure including a Checker contract will be something similar to the following.

// Base interface.
interface IChecker {
    function check(address passerby, bytes memory data) external view;
}

// Simple Checker for base use cases.
abstract contract SimpleChecker is IChecker {
    function check(address passerby, bytes memory data) external view virtual {
        _check(passerby, data);
    }

    function _check(address passerby, bytes memory data) internal view virtual;
}

// Advanced Checker for complex flows
// Used MAIN instead of CONTINUE for
// PRE-MAIN-POST and main check can be done >= 1 times.
abstract contract AdvancedChecker is IChecker {
    enum Phase { PRE, MAIN, POST }

    struct CheckStatus {
        bool preExecuted;
        bool mainExecuted;
        bool postExecuted;
    }

    mapping(address => CheckStatus) public checkStatus;
    uint8 public configFlags;

    function check(address passerby, bytes memory data) external view override {
        if (!_shouldSkipPhase(Phase.PRE)) {
            _checkPre(passerby, data);
        }
        _checkMain(passerby, data);
        if (!_shouldSkipPhase(Phase.POST)) {
            _checkPost(passerby, data);
        }
    }

    function _checkPre(address passerby, bytes memory data) internal view virtual {}
    function _checkMain(address passerby, bytes memory data) internal view virtual;
    function _checkPost(address passerby, bytes memory data) internal view virtual {}
}

// Factory pattern for checker creation.
contract CheckerFactory {
    function createSimpleChecker() external returns (address);
    function createAdvancedChecker(uint8 configFlags) external returns (address);
}

// Modified Excubia base.
abstract contract Excubia is IExcubia {
    IChecker public immutable checker;

    constructor(IChecker _checker) {
        checker = _checker;
    }

    function pass(address passerby, bytes calldata data) external virtual onlyGate {
        checker.check(passerby, data);
        emit GatePassed(passerby, gate);
    }
}