Deployer

This following contract is the OpenPeerEscrowsDeployer and is responsible for deploying individual escrow contracts. This contract deploys escrow contracts for native tokens and ERC20 tokens.

Global settings

  • arbitrator: Address of the arbitrator (currently OP staff, DAO later)

  • feeRecipient: Address to receive the fees

  • _fee: OP fee (bps) ex: 30 == 0.3%

  • stopped: Circuit breaker flag

  • implementation: Address of the OpenPeerEscrow implementation contract

  • feeDiscountNFT: NFT contract for fee discounts

Events

  • ContractCreated(address _seller, address _deployment): Emits when an escrow contract is deployed

Modifiers

  • stopInEmergency: Circuit breaker modifier

Functions

  • constructor(): Initializes the contract with the given parameters

  • deploy(): Deploys a new escrow contract for the msg sender

  • setArbitrator(address _arbitrator): Updates the arbitrator

  • setFeeRecipient(address payable _feeRecipient): Updates the fee recipient

  • setFee(uint256 fee_): Updates the fee

  • setTrustedForwarder(address trustedForwarder): Updates the trusted forwarder

  • updatePartnerFeeBps(address[] calldata _partners, uint256[] calldata _fees): Updates the fees of the partners (bps). Cant be more than 1%. Users can pass the 0x address to avoid it.

  • openpeerFee(): Returns the fee OP will receive from the orders.

  • sellerFee(address _partner): Returns the total fee a seller will pay (bps)

https://github.com/Minke-Labs/openpeer_contracts/blob/main/contracts/OpenPeerEscrowsDeployer.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {Clones} from "@openzeppelin/contracts/proxy/Clones.sol";
import {IERC721} from "@openzeppelin/contracts/interfaces/IERC721.sol";
import {OpenPeerEscrow} from "./OpenPeerEscrow.sol";
import {ERC2771Context} from "./libs/ERC2771Context.sol";
import {Ownable} from "./libs/Ownable.sol";

contract OpenPeerEscrowsDeployer is ERC2771Context, Ownable {
    mapping(address => address) public sellerContracts;
    mapping(address => uint256) public partnerFeeBps;

    /***********************
    +   Global settings   +
    ***********************/
    address public arbitrator;
    address payable public feeRecipient;
    uint256 private fee;
    uint256 public disputeFee;

    bool public stopped;

    address public implementation;

    // NFT contract for fee discounts
    address public feeDiscountNFT;

    /**********************
    +   Events            +
    ***********************/
    event ContractCreated(address _seller, address _deployment);

    /// @notice Settings
    /// @param _arbitrator Address of the arbitrator (currently OP staff)
    /// @param _feeRecipient Address to receive the fees
    /// @param _fee OP fee (bps) ex: 30 == 0.3%
    /// @param _trustedForwarder Forwarder address
    /// @param _feeDiscountNFT NFT contract for fee discounts
    /// @param _disputeFee Dispute fee
    constructor(
        address _arbitrator,
        address payable _feeRecipient,
        uint256 _fee,
        address _trustedForwarder,
        address _feeDiscountNFT,
        uint256 _disputeFee
    ) ERC2771Context(_trustedForwarder) {
        arbitrator = _arbitrator;
        feeRecipient = _feeRecipient;
        fee = _fee;
        feeDiscountNFT = _feeDiscountNFT;
        disputeFee = _disputeFee;
        implementation = address(new OpenPeerEscrow(_trustedForwarder));
    }

    /***********************
    +   Modifiers          +
    ***********************/

    // circuit breaker modifiers
    modifier stopInEmergency() {
        if (stopped) {
            revert("Paused");
        } else {
            _;
        }
    }

    function deploy() external returns (address) {
        address deployment = Clones.clone(implementation);
        OpenPeerEscrow(payable(deployment)).initialize(
            payable(_msgSender()),
            fee,
            arbitrator,
            feeRecipient,
            _trustedForwarder,
            feeDiscountNFT,
            disputeFee
        );
        sellerContracts[_msgSender()] = deployment;
        emit ContractCreated(_msgSender(), deployment);

        return deployment;
    }

    /***********************
    +   Setters           +
    ***********************/

    /// @notice Updates the arbitrator
    /// @param _arbitrator Address of the arbitrator
    function setArbitrator(address _arbitrator) public onlyOwner {
        require(_arbitrator != address(0), "Invalid arbitrator");
        arbitrator = _arbitrator;
    }

    /// @notice Updates the fee recipient
    /// @param _feeRecipient Address of the arbitrator
    function setFeeRecipient(address payable _feeRecipient) public onlyOwner {
        require(_feeRecipient != address(0), "Invalid fee recipient");
        feeRecipient = _feeRecipient;
    }

    /// @notice Updates the fee
    /// @param _fee fee amount (bps)
    function setFee(uint256 _fee) public onlyOwner {
        require(_fee <= 100);

        fee = _fee;
    }

    /// @notice Updates the forwarder
    /// @param trustedForwarder biconomy forwarder
    function setTrustedForwarder(address trustedForwarder) external onlyOwner {
        require(trustedForwarder != address(0), "Invalid trust forwarder");
        _trustedForwarder = trustedForwarder;
    }

    /// @notice Updates the implementation
    /// @param _implementation Address of the implementation
    function setImplementation(
        address payable _implementation
    ) public onlyOwner {
        require(_implementation != address(0), "Invalid implementation");
        implementation = _implementation;
    }

    /// @notice Pauses and activate the contract
    function toggleContractActive() public onlyOwner {
        stopped = !stopped;
    }

    /// @notice Version recipient
    function versionRecipient() external pure returns (string memory) {
        return "1.0";
    }

    /// @notice Updates the NFT contract for fee discounts
    function setFeeDiscountNFT(address _feeDiscountNFT) external onlyOwner {
        feeDiscountNFT = _feeDiscountNFT;
    }

    function updatePartnerFeeBps(
        address[] calldata _partners,
        uint256[] calldata _fees
    ) external onlyOwner {
        require(_partners.length == _fees.length, "Invalid input");

        for (uint256 i = 0; i < _partners.length; i++) {
            require(_fees[i] <= 100, "Invalid fee bps");
            require(_partners[i] != address(0), "Invalid partner address");

            partnerFeeBps[_partners[i]] = _fees[i];
        }
    }

    /***********************
    +   Getters           +
    ***********************/

    function openPeerFee() public view returns (uint256) {
        IERC721 discountNFT = IERC721(feeDiscountNFT);

        if (
            feeDiscountNFT != address(0) &&
            discountNFT.balanceOf(_msgSender()) > 0
        ) {
            return 0;
        }

        return fee;
    }

    function sellerFee(address _partner) public view returns (uint256) {
        return openPeerFee() + partnerFeeBps[_partner];
    }
}

Last updated