Перейти к основному содержимому

PartnerChainBridge

Обзор

PartnerChainBridge — контракт для хранения и передачи цепочек партнеров пользователей из сети Polygon (где находится основной контракт Diamond) в другие EVM-сети. Это позволяет протоколам в различных сетях корректно распределять партнерские вознаграждения, основываясь на данных из основной сети.

Ключевые свойства:

  • Использование прокси-стандарта UUPS для возможности обновления логики.
  • Разграничение прав доступа через AccessControl (роли Admin и Operator).
  • Связка адреса кошелька в локальной сети с глобальным userId из Magnet.
  • Хранение до 15 линий вышестоящих партнеров для каждого уровня (1–15).
  • Дополнительная referralChain для каждого пользователя: userId → level → matrixIndex → referralChain.

Контекст и зависимости

  • Diamond (Polygon): бэкенд-оракул считывает данные о партнерах из Diamond и передает их в PartnerChainBridge в целевой сети.
  • Протоколы ликвидности: используют данные этого контракта для расчета распределений при клейме дохода или покупке NFT.

Состояние

  • OPERATOR_ROLE — хеш роли оператора (keccak256('OPERATOR_ROLE')).
  • partnersChain — маппинг uint32 => mapping(uint8 => uint32[15]), где ключ — ID пользователя из Diamond и уровень (1–15), а значение — массив ID его партнеров.
  • referralChain — маппинг uint32 => mapping(uint8 => mapping(uint32 => uint32[15])), где ключ — ID пользователя, уровень и matrixIndex, а значение — массив ID рефералов.
  • userIds — маппинг address => uint32, связывающий локальный адрес кошелька с ID пользователя из Diamond.

События

UserPartnersChainSet

event UserPartnersChainSet(uint32 indexed userId, address indexed userAddress, uint8 indexed level, uint32[15] partnersChain);

Эмитится при первой установке цепочки партнеров для пользователя на конкретном уровне.

UserReferralChainSet

event UserReferralChainSet(uint32 indexed userId, uint8 indexed level, uint32 indexed matrixIndex, uint32[15] referralChain);

Эмитится при первой установке referral-цепочки для пользователя на конкретном уровне и matrixIndex.

UserAddressUpdated

event UserAddressUpdated(address indexed oldAddress, address indexed newAddress);

Эмитится при смене адреса кошелька, привязанного к конкретному userId.

Ошибки

DeniedByRole

Выбрасывается, если у вызывающего недостаточно прав (отсутствует необходимая роль).

PartnersAlreadySet

Выбрасывается, если попытка вызвать setUserPartnersChain происходит для userId и уровня, у которого уже установлена цепочка.

ReferralAlreadySet

Выбрасывается, если попытка вызвать setUserReferralChain происходит для userId, уровня и matrixIndex, у которых уже установлена referral-цепочка.

InvalidAddress

Выбрасывается при попытке установить или обновить адрес на address(0).

AddressNotInitialized

Выбрасывается, если запрашиваемый ID пользователя или адрес еще не зарегистрирован в системе.

InvalidLevel

Выбрасывается, если указанный уровень выходит за диапазон 1–15.

Функции: управление данными

setUserPartnersChain

function setUserPartnersChain(uint32 userId, address userAddress, uint8 level, uint32[15] memory _partnersChain) external onlyOperator

Назначение: первичная установка цепочки партнеров пользователя на конкретном уровне.

Логика:

  1. Проверяет, что userAddress не нулевой.
  2. Проверяет, что уровень находится в диапазоне 1–15.
  3. Проверяет, что цепочка для данного userId и уровня еще не установлена.
  4. Сохраняет связь адреса с ID и записывает массив партнеров.

setUserReferralChain

function setUserReferralChain(uint32 userId, uint8 level, uint32 matrixIndex, uint32[15] memory _referralChain) external onlyOperator

Назначение: первичная установка referral-цепочки пользователя на конкретном уровне и matrixIndex.

Логика:

  1. Проверяет, что userId валиден.
  2. Проверяет, что уровень находится в диапазоне 1–15.
  3. Проверяет, что referral-цепочка для данного userId, уровня и matrixIndex еще не установлена.
  4. Записывает массив referral-цепочки.

updateUserAddress

function updateUserAddress(address oldAddress, address newAddress) external onlyOperator

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

Функции: получение данных

getUserPartnersByUid

function getUserPartnersByUid(uint32 uid, uint8 level) public view returns (uint32[15] memory)

Возвращает массив из 15 партнеров для заданного ID пользователя и уровня.

getUserPartnersByAddress

function getUserPartnersByAddress(address _address, uint8 level) external view returns (uint32[15] memory)

Возвращает массив из 15 партнеров для заданного адреса кошелька и уровня.

getUserReferralByUid

function getUserReferralByUid(uint32 uid, uint8 level, uint32 matrixIndex) public view returns (uint32[15] memory)

Возвращает массив из 15 referral-партнеров для заданного ID пользователя, уровня и matrixIndex.

getUserReferralByAddress

function getUserReferralByAddress(address _address, uint8 level, uint32 matrixIndex) external view returns (uint32[15] memory)

Возвращает массив из 15 referral-партнеров для заданного адреса кошелька, уровня и matrixIndex.

Функции: системные

initialize

function initialize() public initializer

Инициализирует контракт, устанавливая msg.sender администратором.

_authorizeUpgrade

function _authorizeUpgrade(address newImplementation) internal view override

Внутренняя проверка прав при обновлении контракта (требует DEFAULT_ADMIN_ROLE).

Ограничения и безопасность

  • Однократная установка: цепочка партнеров для конкретного userId и уровня устанавливается только один раз. Referral-цепочка для userId/уровня/matrixIndex тоже устанавливается один раз. Изменение структуры «снизу вверх» не предусмотрено этим контрактом (оно должно происходить в Diamond).
  • Безопасность оракула: контракт полностью доверяет адресу с ролью OPERATOR_ROLE.
  • Лимит уровней: жестко ограничено 15 уровнями (1–15).

Типовой сценарий использования

  1. Оракул вызывает setUserPartnersChain при первом взаимодействии пользователя с протоколом в новой сети для каждого нужного уровня.
  2. При наличии матриц оракул вызывает setUserReferralChain для userId, уровня и matrixIndex.
  3. Смарт-контракт продукта (например, ликвидности) вызывает getUserPartnersByAddress, чтобы получить список ID партнеров для распределения комиссий по нужному уровню.
  4. Продукт отправляет вознаграждения в Diamond или локально, используя полученные ID.