Разработка блокчейн-решения для логистики

Проектируем и разрабатываем блокчейн-решения полного цикла: от архитектуры смарт-контрактов до запуска DeFi-протоколов, NFT-маркетплейсов и криптобирж. Аудит безопасности, токеномика, интеграция с существующей инфраструктурой.
Показано 1 из 1 услугВсе 1306 услуг
Разработка блокчейн-решения для логистики
Сложная
от 2 недель до 3 месяцев
Часто задаваемые вопросы
Направления блокчейн-разработки
Этапы блокчейн-разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1221
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1163
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    855
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1056
  • image_logo-advance_0.png
    Разработка логотипа компании B2B Advance
    561
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    828

Разработка блокчейн-решения для логистики

Логистика — один из немногих секторов, где блокчейн даёт реальное преимущество над традиционными базами данных. Причина: в цепочке поставок участвуют множество независимых сторон (производитель, экспедитор, таможня, порт, перевозчик, получатель), каждая ведёт собственный учёт, и рекончиляция между ними занимает дни и требует дорогих посредников. TradeLens (Maersk + IBM), Morpheus.Network, CargoX — реальные примеры. Блокчейн здесь не «технология ради технологии», а shared ledger для мультисторонней системы без единого доверенного центра.

Что конкретно решает блокчейн в логистике

Три проблемы, которые стоят реальных денег:

Подлинность документов: Bill of Lading — ключевой документ в морской логистике. Традиционно — бумажный, передаётся курьером. Электронный B/L (eBL) давно существует, но централизованные платформы (essDOCS, Bolero) требуют доверия к оператору. CargoX реализует B/L как NFT (ERC-721) на Ethereum — ownership трансферабелен on-chain без посредника.

Прозрачность условий сделки: смарт-контракт-эскроу: оплата высвобождается автоматически при подтверждении доставки. Не нужны банковские гарантии или аккредитивы для небольших сделок.

Трекинг и provenance: для фармацевтики, люкса, продовольствия — критична верификация origin и цепочки хранения (temperature, humidity). IoT-сенсоры + блокчейн = неизменяемый audit trail.

Архитектура документооборота

Bill of Lading как NFT

contract ElectronicBillOfLading is ERC721, AccessControl {
    bytes32 public constant CARRIER_ROLE = keccak256("CARRIER_ROLE");
    bytes32 public constant CUSTOMS_ROLE = keccak256("CUSTOMS_ROLE");
    
    struct ShipmentData {
        string shipmentId;          // внешний ID из TMS
        address shipper;
        address consignee;
        string portOfLoading;
        string portOfDischarge;
        string cargoDescription;
        uint256 quantity;
        string unit;                // TEU, tonnes, pallets
        uint256 issuedAt;
        ShipmentStatus status;
        bytes32 dataHash;          // хеш полного документа в IPFS
    }
    
    enum ShipmentStatus {
        Issued,
        InTransit,
        ArrivedAtPort,
        CustomsCleared,
        Delivered,
        Surrendered
    }
    
    mapping(uint256 => ShipmentData) public shipments;
    mapping(uint256 => string[]) public statusHistory; // лог изменений статуса
    
    uint256 private _tokenIdCounter;
    
    function issueBL(
        address consignee,
        string calldata shipmentId,
        string calldata portOfLoading,
        string calldata portOfDischarge,
        string calldata cargoDescription,
        uint256 quantity,
        string calldata unit,
        bytes32 dataHash
    ) external onlyRole(CARRIER_ROLE) returns (uint256) {
        uint256 tokenId = ++_tokenIdCounter;
        
        _mint(consignee, tokenId);
        
        shipments[tokenId] = ShipmentData({
            shipmentId: shipmentId,
            shipper: msg.sender,
            consignee: consignee,
            portOfLoading: portOfLoading,
            portOfDischarge: portOfDischarge,
            cargoDescription: cargoDescription,
            quantity: quantity,
            unit: unit,
            issuedAt: block.timestamp,
            status: ShipmentStatus.Issued,
            dataHash: dataHash
        });
        
        emit BLIssued(tokenId, consignee, shipmentId);
        return tokenId;
    }
    
    function updateStatus(
        uint256 tokenId,
        ShipmentStatus newStatus,
        string calldata note
    ) external {
        ShipmentData storage shipment = shipments[tokenId];
        
        // Проверка ролей для каждого перехода
        if (newStatus == ShipmentStatus.CustomsCleared) {
            require(hasRole(CUSTOMS_ROLE, msg.sender), "Only customs");
        } else if (newStatus == ShipmentStatus.Delivered) {
            require(ownerOf(tokenId) == msg.sender, "Only consignee");
        } else {
            require(hasRole(CARRIER_ROLE, msg.sender), "Only carrier");
        }
        
        ShipmentStatus prevStatus = shipment.status;
        shipment.status = newStatus;
        statusHistory[tokenId].push(string(abi.encodePacked(
            Strings.toString(block.timestamp), ":", note
        )));
        
        emit StatusUpdated(tokenId, prevStatus, newStatus, msg.sender);
    }
    
    // Override transfer — B/L может передаваться только при определённых статусах
    function _beforeTokenTransfer(address from, address to, uint256 tokenId, uint256 batchSize) 
        internal override 
    {
        super._beforeTokenTransfer(from, to, tokenId, batchSize);
        
        if (from != address(0)) { // не mint
            ShipmentStatus status = shipments[tokenId].status;
            require(
                status == ShipmentStatus.Issued || status == ShipmentStatus.InTransit,
                "BL not transferable in current status"
            );
        }
    }
}

Эскроу для платежей

Оплата замороженной в смарт-контракте до подтверждения delivery:

contract ShipmentEscrow {
    enum EscrowState { Created, Funded, Released, Disputed, Refunded }
    
    struct Escrow {
        address buyer;
        address seller;
        address carrier;
        uint256 amount;
        address token;              // USDC или другой stablecoin
        uint256 blTokenId;          // ID B/L NFT
        address blContract;
        EscrowState state;
        uint256 releaseDeadline;   // если нет dispute до deadline — авто-release
    }
    
    mapping(bytes32 => Escrow) public escrows;
    
    function createEscrow(
        address seller,
        address carrier,
        uint256 amount,
        address token,
        uint256 blTokenId,
        address blContract,
        uint256 deliveryDeadline
    ) external returns (bytes32 escrowId) {
        escrowId = keccak256(abi.encodePacked(msg.sender, seller, blTokenId, block.timestamp));
        
        IERC20(token).safeTransferFrom(msg.sender, address(this), amount);
        
        escrows[escrowId] = Escrow({
            buyer: msg.sender,
            seller: seller,
            carrier: carrier,
            amount: amount,
            token: token,
            blTokenId: blTokenId,
            blContract: blContract,
            state: EscrowState.Funded,
            releaseDeadline: deliveryDeadline + 7 days // буфер для dispute
        });
    }
    
    function confirmDelivery(bytes32 escrowId) external {
        Escrow storage escrow = escrows[escrowId];
        require(msg.sender == escrow.buyer, "Only buyer");
        require(escrow.state == EscrowState.Funded, "Wrong state");
        
        // Проверяем что B/L имеет статус Delivered
        ElectronicBillOfLading bl = ElectronicBillOfLading(escrow.blContract);
        require(
            bl.shipments(escrow.blTokenId).status == ElectronicBillOfLading.ShipmentStatus.Delivered,
            "Not delivered on-chain"
        );
        
        escrow.state = EscrowState.Released;
        IERC20(escrow.token).safeTransfer(escrow.seller, escrow.amount);
    }
}

IoT-интеграция: данные с датчиков в блокчейн

Для cold chain (фармацевтика, продукты) важна верификация условий хранения. IoT → блокчейн требует решения проблемы oracle: смарт-контракт не может получить данные с физических датчиков напрямую.

Архитектура IoT oracle

IoT датчики (температура, влажность, GPS)
    ↓ MQTT / LoRaWAN
IoT шлюз (Raspberry Pi / промышленный гейт)
    ↓ подписанные пакеты данных
Oracle сервис (Chainlink Functions или собственный)
    ↓ on-chain транзакция
Смарт-контракт (запись телеметрии)
contract ShipmentTelemetry {
    struct TelemetryRecord {
        uint256 timestamp;
        int16 temperature;      // в десятых долях градуса (156 = 15.6°C)
        uint16 humidity;        // в десятых процента
        int32 latitude;         // в микроградусах
        int32 longitude;
        address oracle;         // кто подписал данные
    }
    
    mapping(uint256 => TelemetryRecord[]) public telemetry; // tokenId => records
    mapping(uint256 => bool) public conditionViolated;     // были ли нарушения
    
    // Допустимые диапазоны для груза
    struct ConditionRequirements {
        int16 minTemp;
        int16 maxTemp;
        uint16 maxHumidity;
    }
    mapping(uint256 => ConditionRequirements) public requirements;
    
    function submitTelemetry(
        uint256 shipmentTokenId,
        int16 temperature,
        uint16 humidity,
        int32 lat,
        int32 lon,
        bytes calldata oracleSignature
    ) external {
        // Верифицируем подпись oracle
        bytes32 dataHash = keccak256(abi.encodePacked(
            shipmentTokenId, temperature, humidity, lat, lon, block.timestamp / 300 // 5-мин окно
        ));
        address signer = ECDSA.recover(dataHash.toEthSignedMessageHash(), oracleSignature);
        require(isApprovedOracle(signer), "Unauthorized oracle");
        
        telemetry[shipmentTokenId].push(TelemetryRecord({
            timestamp: block.timestamp,
            temperature: temperature,
            humidity: humidity,
            latitude: lat,
            longitude: lon,
            oracle: signer
        }));
        
        // Проверяем нарушения условий
        ConditionRequirements memory req = requirements[shipmentTokenId];
        if (temperature < req.minTemp || temperature > req.maxTemp || humidity > req.maxHumidity) {
            conditionViolated[shipmentTokenId] = true;
            emit ConditionViolation(shipmentTokenId, temperature, humidity, block.timestamp);
        }
    }
}

Chainlink Functions для агрегации IoT данных

Вместо собственного oracle можно использовать Chainlink Functions — позволяет выполнять произвольный JavaScript off-chain и отправлять результат on-chain:

// Chainlink Functions source code (выполняется в decentralized oracle сети)
const shipmentId = args[0];
const apiKey = secrets.iotApiKey;

const response = await Functions.makeHttpRequest({
  url: `https://iot-api.example.com/telemetry/${shipmentId}/latest`,
  headers: { "X-API-Key": apiKey },
});

const { temperature, humidity, lat, lon } = response.data;

// Encode в bytes для on-chain
return Functions.encodeString(
  JSON.stringify({ temperature, humidity, lat, lon })
);

Выбор блокчейна для логистики

Публичный блокчейн (Polygon, Arbitrum): максимальная открытость, permissionless участники, токенизация B/L с DeFi интеграцией. Минусы: газ, публичность транзакций (конкуренты видят объёмы).

Enterprise blockchain (Hyperledger Fabric, R3 Corda): приватные данные, permissioned участники, нет газа. Минусы: нет токенизации, нет composability с DeFi, высокая стоимость нод.

Hybrid: приватные данные в Fabric, хеши в публичный блокчейн для notarization. Сложнее в разработке, но сочетает преимущества обоих.

Для B2B логистического проекта с известными участниками — Hyperledger Fabric или Polygon с private transactions (zk-based). Для открытого протокола с токенизацией — Polygon или Arbitrum.

Интеграция с существующими системами

Логистические TMS (Transportation Management Systems), ERP (SAP, Oracle TMS) имеют REST/SOAP API. Интеграционный слой:

class LogisticsIntegration {
  private web3Provider: Provider;
  private blContract: ElectronicBillOfLading;
  
  // Webhook от TMS при изменении статуса груза
  async handleTMSStatusUpdate(event: TMSEvent) {
    const { shipmentId, newStatus, timestamp, operator } = event;
    
    const tokenId = await this.getTokenIdByShipmentId(shipmentId);
    const onChainStatus = this.mapTMSStatusToOnChain(newStatus);
    
    // Отправляем транзакцию
    const tx = await this.blContract.updateStatus(
      tokenId,
      onChainStatus,
      `TMS update: ${newStatus} at ${timestamp}`
    );
    
    await tx.wait();
    
    // Обновляем локальную БД
    await this.db.shipments.update({
      where: { shipmentId },
      data: { lastTxHash: tx.hash, onChainStatus },
    });
  }
}

Стек разработки

Компонент Технология
B/L контракты Solidity + ERC-721 + Foundry
Escrow Solidity + OpenZeppelin
IoT oracle Chainlink Functions или собственный oracle с HSM подписью
Backend API Node.js/TypeScript + Fastify
Документы IPFS + AES encryption для private docs
Интеграция TMS REST webhooks + message queue (RabbitMQ)
Frontend Next.js + wagmi + shadcn

Сроки

MVP (B/L NFT + базовый трекинг статусов + простой эскроу): 6–8 недель.

Production с IoT-интеграцией, мультистороним workflow, TMS интеграцией и audit reporting: 4–6 месяцев.

Ключевая сложность не техническая, а организационная: все стороны цепочки поставок должны принять систему. Техническая интеграция с каждым участником добавляет 2–4 недели работы.