B2B Contract Automation

What it does:
Automates creation, execution, and enforcement of B2B contracts on-chain, including payments, delivery terms, and compliance clauses.

Why it matters:
Reduces administrative overhead, ensures enforceable agreements, minimizes disputes, and provides transparent, auditable business relationships.

How it works:

  • Businesses create on-chain contracts specifying terms, payment schedules, and obligations

  • Smart contracts enforce conditions such as delivery confirmation, milestone completion, or regulatory compliance

  • Payments are released automatically based on fulfillment of contract terms

  • Parties can monitor contract status, approvals, and obligations on-chain

  • Disputes can be resolved via multi-signature approvals or arbitration mechanisms

  • Integrates with Automated Trade Finance, Supply Chain Traceability, and Escrow Systems

  • Public dashboards provide visibility into active contracts, payments, and obligations

      // SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "@openzeppelin/contracts/access/Ownable.sol";

/**
 * @title B2BContractAutomation
 * @author Nam
 * @notice Automates B2B contracts, payments, and fulfillment on-chain
 */
contract B2BContractAutomation is Ownable {

    struct ContractAgreement {
        address payable partyA;
        address payable partyB;
        uint256 totalAmount;
        bool partyADelivered;
        bool partyBApproved;
        bool paid;
        string terms;
    }

    mapping(uint256 => ContractAgreement) public contracts;
    uint256 public contractCount;

    mapping(address => bool) public authorizedArbiters;

    // -------------------- EVENTS --------------------

    event ContractCreated(uint256 indexed contractId, address partyA, address partyB, uint256 totalAmount, string terms);
    event DeliveryConfirmed(uint256 indexed contractId, address party);
    event ApprovalGranted(uint256 indexed contractId, address approver);
    event PaymentReleased(uint256 indexed contractId, uint256 amount);
    event ArbiterApproved(address arbiter);

    // -------------------- ARBITER MANAGEMENT --------------------

    function approveArbiter(address _arbiter) external onlyOwner {
        authorizedArbiters[_arbiter] = true;
        emit ArbiterApproved(_arbiter);
    }

    function revokeArbiter(address _arbiter) external onlyOwner {
        authorizedArbiters[_arbiter] = false;
    }

    modifier onlyArbiter() {
        require(authorizedArbiters[msg.sender], "Not authorized arbiter");
        _;
    }

    // -------------------- CONTRACT CREATION --------------------

    function createContract(address payable _partyB, string calldata _terms) external payable {
        require(msg.value > 0, "Payment required");

        contractCount += 1;
        contracts[contractCount] = ContractAgreement({
            partyA: payable(msg.sender),
            partyB: _partyB,
            totalAmount: msg.value,
            partyADelivered: false,
            partyBApproved: false,
            paid: false,
            terms: _terms
        });

        emit ContractCreated(contractCount, msg.sender, _partyB, msg.value, _terms);
    }

    // -------------------- FULFILLMENT & APPROVAL --------------------

    function confirmDelivery(uint256 _contractId) external {
        ContractAgreement storage c = contracts[_contractId];
        require(msg.sender == c.partyA, "Only Party A can confirm delivery");
        require(!c.partyADelivered, "Already confirmed");

        c.partyADelivered = true;
        emit DeliveryConfirmed(_contractId, msg.sender);
    }

    function approveContract(uint256 _contractId) external {
        ContractAgreement storage c = contracts[_contractId];
        require(msg.sender == c.partyB, "Only Party B can approve");
        require(c.partyADelivered, "Delivery not confirmed");
        require(!c.partyBApproved, "Already approved");

        c.partyBApproved = true;
        emit ApprovalGranted(_contractId, msg.sender);
    }

    // -------------------- PAYMENT RELEASE --------------------

    function releasePayment(uint256 _contractId) external {
        ContractAgreement storage c = contracts[_contractId];
        require(c.partyADelivered && c.partyBApproved, "Conditions not met");
        require(!c.paid, "Already paid");

        c.paid = true;
        c.partyB.transfer(c.totalAmount);

        emit PaymentReleased(_contractId, c.totalAmount);
    }

    // -------------------- ARBITRATION --------------------

    function forceReleasePayment(uint256 _contractId) external onlyArbiter {
        ContractAgreement storage c = contracts[_contractId];
        require(!c.paid, "Already paid");

        c.paid = true;
        c.partyB.transfer(c.totalAmount);

        emit PaymentReleased(_contractId, c.totalAmount);
    }
}