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
Назначение: первичная установка цепочки партнеров пользователя на конкретном уровне.
Логика:
- Проверяет, что
userAddressне нулевой. - Проверяет, что уровень находится в диапазоне 1–15.
- Проверяет, что цепочка для данного
userIdи уровня еще не установлена. - Сохраняет связь адреса с ID и записывает массив партнеров.
setUserReferralChain
function setUserReferralChain(uint32 userId, uint8 level, uint32 matrixIndex, uint32[15] memory _referralChain) external onlyOperator
Назначение: первичная установка referral-цепочки пользователя на конкретном уровне и matrixIndex.
Логика:
- Проверяет, что
userIdвалиден. - Проверяет, что уровень находится в диапазоне 1–15.
- Проверяет, что referral-цепочка для данного
userId, уровня иmatrixIndexеще не установлена. - Записывает массив 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).
Типовой сценарий исп ользования
- Оракул вызывает
setUserPartnersChainпри первом взаимодействии пользователя с протоколом в новой сети для каждого нужного уровня. - При наличии матриц оракул вызывает
setUserReferralChainдляuserId, уровня иmatrixIndex. - Смарт-контракт продукта (например, ликвидности) вызывает
getUserPartnersByAddress, чтобы получить список ID партнеров для распределения комиссий по нужному уровню. - Продукт отправляет вознаграждения в Diamond или локально, используя полученные ID.