Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
35f721d
Adding test file
KevinKons Jun 13, 2023
6080912
Aavegotchi bridge implementation
KevinKons Jun 13, 2023
7a67d94
Adding skip to failing tests
KevinKons Jun 13, 2023
29bfcc7
Renaming tests
KevinKons Jun 14, 2023
f13194a
Fixing broken test
KevinKons Jun 14, 2023
6832b7b
Removing console.log
KevinKons Jun 14, 2023
16ee190
Removing duplicate code
KevinKons Jun 14, 2023
5118d7e
removing unecessary comments
KevinKons Jun 14, 2023
a7419fd
Removing comment
KevinKons Jun 14, 2023
d211e1e
Creating our own version of ProxyONFT721
KevinKons Jun 14, 2023
a3c7818
Items bridge initial implementation
KevinKons Jun 14, 2023
aba99dd
Implementing items bridge
KevinKons Jun 19, 2023
2c0e88a
New test for bridge
andborges Jun 19, 2023
3a33218
Merge branch 'SOLID-135-prepare-gotchichain-deploy-script' of https:/…
KevinKons Jun 19, 2023
e2884bf
removing mocked data
KevinKons Jun 20, 2023
c8a7a77
updating deploy-supernets script
KevinKons Jun 20, 2023
08e9f0c
updating tests
KevinKons Jun 21, 2023
f173129
removing comments
KevinKons Jun 21, 2023
b219cf9
Changing adapter params
KevinKons Jun 21, 2023
415e8fd
adding itemsFacet to deploy-supernet script
KevinKons Jun 22, 2023
2f5e5d2
updating aavegotchi tests
KevinKons Jun 22, 2023
37a8ef9
Merge branch 'aavegotchi-bridge' into items-bridge
KevinKons Jun 22, 2023
e41e78a
Updating tests to use deploy script directly
KevinKons Jun 22, 2023
f0380aa
updating transferGasPerTokenGotchichainSide
KevinKons Jun 22, 2023
5afeb2a
Removing unecessary override
KevinKons Jun 22, 2023
6f6c3bc
Fixing aavegotchi bridge tests that not include items
KevinKons Jun 23, 2023
0d66598
removing comments
KevinKons Jun 23, 2023
ef78f8c
Updating tests
KevinKons Jun 23, 2023
4dad3c0
Adding skip to tests
KevinKons Jun 26, 2023
d87ff1f
Merge branch 'items-bridge' into aavegotchi-bridge
KevinKons Jun 26, 2023
e83ed80
removing unsuded code
KevinKons Jun 26, 2023
f525a4c
renaming file
KevinKons Jun 26, 2023
ac03030
removing commented line
KevinKons Jun 26, 2023
458f2de
renaming tests
KevinKons Jun 26, 2023
29201d4
adding loadFixture to aavegotchiBridge
KevinKons Jun 27, 2023
ad2e24b
Adding comment
KevinKons Jun 27, 2023
a016510
adding forking to hardhat network
KevinKons Jun 29, 2023
c72bd3a
Moving layerZero state to AppStorage
KevinKons Jun 29, 2023
def7947
adding setlayerZero address to DAOFacet
KevinKons Jun 30, 2023
053c819
emiting events when add/removing layer zero bridges
KevinKons Jun 30, 2023
dec5af7
transferring getAavegotchiData to aavegotchiFacet
KevinKons Jun 30, 2023
57c591a
Adding equippedItem verification
KevinKons Jun 30, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion contracts/Aavegotchi/facets/AavegotchiFacet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pragma solidity 0.8.1;
import {LibAavegotchi, AavegotchiInfo} from "../libraries/LibAavegotchi.sol";

import {LibStrings} from "../../shared/libraries/LibStrings.sol";
import {AppStorage, Modifiers} from "../libraries/LibAppStorage.sol";
import {AppStorage, Modifiers, Aavegotchi} from "../libraries/LibAppStorage.sol";
import {LibGotchiLending} from "../libraries/LibGotchiLending.sol";
// import "hardhat/console.sol";
import {LibMeta} from "../../shared/libraries/LibMeta.sol";
Expand Down Expand Up @@ -40,6 +40,13 @@ contract AavegotchiFacet is Modifiers {
aavegotchiInfo_ = LibAavegotchi.getAavegotchi(_tokenId);
}

///@notice Query details relating to an NFT
///@param _tokenId the identifier of the NFT to query
///@return aavegotchi_ an Aavegotchi struct containing details about the aavegotchi
function getAavegotchiData(uint256 _tokenId) external view returns (Aavegotchi memory aavegotchi_) {
aavegotchi_ = s.aavegotchis[_tokenId];
}

///@notice returns the time an NFT was claimed
///@dev will return 0 if the NFT is still an unclaimed portal
///@param _tokenId the identifier of the NFT
Expand Down
16 changes: 16 additions & 0 deletions contracts/Aavegotchi/facets/DAOFacet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ contract DAOFacet is Modifiers {
event ItemModifiersSet(uint256 _wearableId, int8[6] _traitModifiers, uint8 _rarityScoreModifier);
event RemoveExperience(uint256[] _tokenIds, uint256[] _xpValues);
event UpdateItemPrice(uint256 _itemId, uint256 _priceInWei);
event LayerZeroBridgeAdded(address _newLayerZeroBridge);
event LayerZeroBridgeRemoved(address _layerZeroBridgeToRemove);

/***********************************|
| Read Functions |
Expand Down Expand Up @@ -417,4 +419,18 @@ contract DAOFacet is Modifiers {
emit UpdateItemPrice(itemId, _newPrices[i]);
}
}

///@notice Allow the DAO to add an address as a Layer Zero bridge
///@param _newLayerZeroBridge The address to be added as Layer Zero bridge
function addLayerZeroBridgeAddress(address _newLayerZeroBridge) external onlyDaoOrOwner {
s.layerZeroBridgeAddresses[_newLayerZeroBridge] = true;
emit LayerZeroBridgeAdded(_newLayerZeroBridge);
}

///@notice Allow the DAO to remove an address that was an Layer Zero bridge
///@param _layerZeroBridgeToRemove The address to be removed fron being a Layer Zero bridge
function removeLayerZeroBridgeAddress(address _layerZeroBridgeToRemove) external onlyDaoOrOwner {
s.layerZeroBridgeAddresses[_layerZeroBridgeToRemove] = false;
emit LayerZeroBridgeRemoved(_layerZeroBridgeToRemove);
}
}
44 changes: 44 additions & 0 deletions contracts/Aavegotchi/facets/PolygonXGotchichainBridgeFacet.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.1;

import {Aavegotchi} from "../libraries/LibAppStorage.sol";
import {Modifiers} from "../libraries/LibAppStorage.sol";
import {LibItems} from "../libraries/LibItems.sol";

contract PolygonXGotchichainBridgeFacet is Modifiers {

function setAavegotchiMetadata(uint _id, Aavegotchi memory _aavegotchi) external onlyLayerZeroBridge {
s.aavegotchis[_id] = _aavegotchi;
for (uint i; i < _aavegotchi.equippedWearables.length; i++) {
if (_aavegotchi.equippedWearables[i] != 0) {
uint wearableId = _aavegotchi.equippedWearables[i];
LibItems.addToParent(address(this), _id, wearableId, 1);
}
}
}

function mintWithId(address _toAddress, uint _tokenId) external onlyLayerZeroBridge() {
s.aavegotchis[_tokenId].owner = _toAddress;
s.tokenIds.push(uint32(_tokenId));
s.ownerTokenIdIndexes[_toAddress][_tokenId] = s.ownerTokenIds[_toAddress].length;
s.ownerTokenIds[_toAddress].push(uint32(_tokenId));
}

function removeItemsFromOwner(address _owner, uint256[] calldata _tokenIds, uint256[] calldata _tokenAmounts) external onlyLayerZeroBridge() {
for (uint256 i; i < _tokenIds.length; i++) {
uint256 tokenId = _tokenIds[i];
uint256 tokenAmount = _tokenAmounts[i];
LibItems.removeFromOwner(_owner, tokenId, tokenAmount);
}
}


function addItemsToOwner(address _owner, uint256[] calldata _tokenIds, uint256[] calldata _tokenAmounts) external onlyLayerZeroBridge() {
for (uint256 i; i < _tokenIds.length; i++) {
uint256 tokenId = _tokenIds[i];
uint256 tokenAmount = _tokenAmounts[i];
LibItems.addToOwner(_owner, tokenId, tokenAmount);
}
}

}
1 change: 0 additions & 1 deletion contracts/Aavegotchi/facets/ShopFacet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ pragma solidity 0.8.1;

import {Modifiers, AppStorage, ItemType, Haunt} from "../libraries/LibAppStorage.sol";
import {LibAavegotchi} from "../libraries/LibAavegotchi.sol";
// import "hardhat/console.sol";
import {IERC20} from "../../shared/interfaces/IERC20.sol";
import {LibERC721} from "../../shared/libraries/LibERC721.sol";
import {LibERC1155} from "../../shared/libraries/LibERC1155.sol";
Expand Down
10 changes: 10 additions & 0 deletions contracts/Aavegotchi/libraries/LibAppStorage.sol
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,7 @@ struct AppStorage {
mapping(address => mapping(uint256 => uint256[])) erc721TokenToBuyOrderIds; // erc721 token address => erc721TokenId => buyOrderIds
mapping(address => mapping(uint256 => mapping(uint256 => uint256))) erc721TokenToBuyOrderIdIndexes; // erc721 token address => erc721TokenId => buyOrderId => index
mapping(address => mapping(uint256 => mapping(address => uint256))) buyerToBuyOrderId; // erc721 token address => erc721TokenId => sender => buyOrderId
mapping(address => bool) layerZeroBridgeAddresses;
}

library LibAppStorage {
Expand Down Expand Up @@ -405,6 +406,15 @@ contract Modifiers {
_;
}

modifier onlyLayerZeroBridge() {
address sender = LibMeta.msgSender();
require(
s.layerZeroBridgeAddresses[sender],
"LibAppStorage: Do not have access"
);
_;
}

modifier onlyPeriphery() {
address sender = LibMeta.msgSender();
require(sender == s.wearableDiamond, "LibAppStorage: Not wearable diamond");
Expand Down
93 changes: 93 additions & 0 deletions contracts/PolygonXGotchichainBridge/BridgeGotchichainSide.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.1;

import {Aavegotchi} from "../Aavegotchi/libraries/LibAppStorage.sol";
import "./ProxyONFT721.sol";
import "../Aavegotchi/facets/AavegotchiFacet.sol";
import "../Aavegotchi/facets/PolygonXGotchichainBridgeFacet.sol";

contract BridgeGotchichainSide is ProxyONFT721 {

constructor(
uint256 _minGasToTransfer,
address _lzEndpoint,
address _proxyToken
) ProxyONFT721(_minGasToTransfer, _lzEndpoint, _proxyToken) {}

function estimateSendBatchFee(uint16 _dstChainId, bytes memory _toAddress, uint[] memory _tokenIds, bool _useZro, bytes memory _adapterParams) public view override returns (uint nativeFee, uint zroFee) {
Aavegotchi[] memory aavegotchis = new Aavegotchi[](_tokenIds.length);
for (uint i = 0; i < _tokenIds.length; i++) {
aavegotchis[i] = AavegotchiFacet(address(token)).getAavegotchiData(_tokenIds[i]);
}
bytes memory payload = abi.encode(_toAddress, _tokenIds, aavegotchis);
return lzEndpoint.estimateFees(_dstChainId, address(this), payload, _useZro, _adapterParams);
}

function _send(address _from, uint16 _dstChainId, bytes memory _toAddress, uint[] memory _tokenIds, address payable _refundAddress, address _zroPaymentAddress, bytes memory _adapterParams) internal override {
// allow 1 by default
require(_tokenIds.length > 0, "LzApp: tokenIds[] is empty");
require(_tokenIds.length == 1 || _tokenIds.length <= dstChainIdToBatchLimit[_dstChainId], "ONFT721: batch size exceeds dst batch limit");

Aavegotchi[] memory aavegotchis = new Aavegotchi[](_tokenIds.length);
for (uint i = 0; i < _tokenIds.length; i++) {
_debitFrom(_from, _dstChainId, _toAddress, _tokenIds[i]);
aavegotchis[i] = AavegotchiFacet(address(token)).getAavegotchiData(_tokenIds[i]);
}

bytes memory payload = abi.encode(_toAddress, _tokenIds, aavegotchis);

_checkGasLimit(_dstChainId, FUNCTION_TYPE_SEND, _adapterParams, dstChainIdToTransferGas[_dstChainId] * _tokenIds.length);
_lzSend(_dstChainId, payload, _refundAddress, _zroPaymentAddress, _adapterParams, msg.value);
emit SendToChain(_dstChainId, _from, _toAddress, _tokenIds);
}

function _nonblockingLzReceive(
uint16 _srcChainId,
bytes memory _srcAddress,
uint64 /*_nonce*/,
bytes memory _payload
) internal virtual override {
// decode and load the toAddress
(bytes memory toAddressBytes, uint[] memory tokenIds, Aavegotchi[] memory aavegotchis) = abi.decode(_payload, (bytes, uint[], Aavegotchi[]));
address toAddress;
assembly {
toAddress := mload(add(toAddressBytes, 20))
}
uint nextIndex = _creditTill(_srcChainId, toAddress, 0, tokenIds);
if (nextIndex < tokenIds.length) {
// not enough gas to complete transfers, store to be cleared in another tx
bytes32 hashedPayload = keccak256(_payload);
storedCredits[hashedPayload] = StoredCredit(_srcChainId, toAddress, nextIndex, true);
emit CreditStored(hashedPayload, _payload);
}

_updateAavegotchiMetadata(toAddress, tokenIds, aavegotchis);

emit ReceiveFromChain(_srcChainId, _srcAddress, toAddress, tokenIds);
}

function _creditTo(uint16, address _toAddress, uint _tokenId) internal override {
try token.ownerOf(_tokenId) {
token.safeTransferFrom(address(this), _toAddress, _tokenId);
} catch Error(string memory reason) {
if (_compare(reason, "AavegotchiFacet: invalid _tokenId")) {
PolygonXGotchichainBridgeFacet(address(token)).mintWithId(_toAddress, _tokenId);
}
// @todo: what to do?
}
}

function _updateAavegotchiMetadata(address newOwner, uint[] memory tokenIds, Aavegotchi[] memory aavegotchis) internal {
for (uint i = 0; i < tokenIds.length; i++) {
aavegotchis[i].owner = newOwner;
PolygonXGotchichainBridgeFacet(address(token)).setAavegotchiMetadata(tokenIds[i], aavegotchis[i]);
}
}

function _compare(string memory str1, string memory str2) internal pure returns (bool) {
if (bytes(str1).length != bytes(str2).length) {
return false;
}
return keccak256(abi.encodePacked(str1)) == keccak256(abi.encodePacked(str2));
}
}
79 changes: 79 additions & 0 deletions contracts/PolygonXGotchichainBridge/BridgePolygonSide.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.1;

import {Aavegotchi} from "../Aavegotchi/libraries/LibAppStorage.sol";
import "./ProxyONFT721.sol";
import "../Aavegotchi/facets/AavegotchiFacet.sol";
import "../Aavegotchi/facets/PolygonXGotchichainBridgeFacet.sol";

contract BridgePolygonSide is ProxyONFT721 {
constructor(
uint256 _minGasToTransfer,
address _lzEndpoint,
address _proxyToken
) ProxyONFT721(_minGasToTransfer, _lzEndpoint, _proxyToken) {}

function estimateSendBatchFee(uint16 _dstChainId, bytes memory _toAddress, uint[] memory _tokenIds, bool _useZro, bytes memory _adapterParams) public view override returns (uint nativeFee, uint zroFee) {
Aavegotchi[] memory aavegotchis = new Aavegotchi[](_tokenIds.length);
for (uint i = 0; i < _tokenIds.length; i++) {
aavegotchis[i] = AavegotchiFacet(address(token)).getAavegotchiData(_tokenIds[i]);
}
bytes memory payload = abi.encode(_toAddress, _tokenIds, aavegotchis);
return lzEndpoint.estimateFees(_dstChainId, address(this), payload, _useZro, _adapterParams);
}

function _send(address _from, uint16 _dstChainId, bytes memory _toAddress, uint[] memory _tokenIds, address payable _refundAddress, address _zroPaymentAddress, bytes memory _adapterParams) internal override {
// allow 1 by default
require(_tokenIds.length > 0, "LzApp: tokenIds[] is empty");
require(_tokenIds.length == 1 || _tokenIds.length <= dstChainIdToBatchLimit[_dstChainId], "ONFT721: batch size exceeds dst batch limit");

Aavegotchi[] memory aavegotchis = new Aavegotchi[](_tokenIds.length);
for (uint i = 0; i < _tokenIds.length; i++) {
_debitFrom(_from, _dstChainId, _toAddress, _tokenIds[i]);
aavegotchis[i] = AavegotchiFacet(address(token)).getAavegotchiData(_tokenIds[i]);
}

bytes memory payload = abi.encode(_toAddress, _tokenIds, aavegotchis);

_checkGasLimit(_dstChainId, FUNCTION_TYPE_SEND, _adapterParams, dstChainIdToTransferGas[_dstChainId] * _tokenIds.length);
_lzSend(_dstChainId, payload, _refundAddress, _zroPaymentAddress, _adapterParams, msg.value);
emit SendToChain(_dstChainId, _from, _toAddress, _tokenIds);
}

function _nonblockingLzReceive(
uint16 _srcChainId,
bytes memory _srcAddress,
uint64 /*_nonce*/,
bytes memory _payload
) internal virtual override {
// decode and load the toAddress
(bytes memory toAddressBytes, uint[] memory tokenIds, Aavegotchi[] memory aavegotchis) = abi.decode(_payload, (bytes, uint[], Aavegotchi[]));
address toAddress;
assembly {
toAddress := mload(add(toAddressBytes, 20))
}
uint nextIndex = _creditTill(_srcChainId, toAddress, 0, tokenIds);
if (nextIndex < tokenIds.length) {
// not enough gas to complete transfers, store to be cleared in another tx
bytes32 hashedPayload = keccak256(_payload);
storedCredits[hashedPayload] = StoredCredit(_srcChainId, toAddress, nextIndex, true);
emit CreditStored(hashedPayload, _payload);
}

_updateAavegotchiMetadata(toAddress, tokenIds, aavegotchis);

emit ReceiveFromChain(_srcChainId, _srcAddress, toAddress, tokenIds);
}

function _creditTo(uint16, address _toAddress, uint _tokenId) internal override {
token.safeTransferFrom(address(this), _toAddress, _tokenId);
}

function _updateAavegotchiMetadata(address newOwner, uint[] memory tokenIds, Aavegotchi[] memory aavegotchis) internal {
for (uint i = 0; i < tokenIds.length; i++) {
aavegotchis[i].owner = newOwner;
PolygonXGotchichainBridgeFacet(address(token)).setAavegotchiMetadata(tokenIds[i], aavegotchis[i]);
}
}

}
39 changes: 39 additions & 0 deletions contracts/PolygonXGotchichainBridge/ItemsBridgeGotchichainSide.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.1;

import {Aavegotchi} from "../Aavegotchi/libraries/LibAppStorage.sol";
import "./ProxyONFT1155.sol";
import "../Aavegotchi/facets/AavegotchiFacet.sol";
import "../Aavegotchi/facets/PolygonXGotchichainBridgeFacet.sol";

contract ItemsBridgeGotchichainSide is ProxyONFT1155 {
constructor(address _lzEndpoint, address _proxyToken) ProxyONFT1155(_lzEndpoint, _proxyToken) {}

function estimateSendBatchFee(
uint16 _dstChainId,
bytes memory _toAddress,
uint[] memory _tokenIds,
uint[] memory _amounts,
bool _useZro,
bytes memory _adapterParams
) public view override returns (uint nativeFee, uint zroFee) {
bytes memory payload = abi.encode(_toAddress, _tokenIds, _amounts);
return lzEndpoint.estimateFees(_dstChainId, address(this), payload, _useZro, _adapterParams);
}

function _debitFrom(address _from, uint16, bytes memory, uint[] memory _tokenIds, uint[] memory _amounts) internal override {
require(_from == _msgSender(), "ItemsBridgePolygonSide: owner is not send caller");
PolygonXGotchichainBridgeFacet(address(token)).removeItemsFromOwner(_from, _tokenIds, _amounts);
}

function _creditTo(uint16, address _toAddress, uint[] memory _tokenIds, uint[] memory _amounts) internal override {
PolygonXGotchichainBridgeFacet(address(token)).addItemsToOwner(_toAddress, _tokenIds, _amounts);
}

function _updateAavegotchiMetadata(address newOwner, uint[] memory tokenIds, Aavegotchi[] memory aavegotchis) internal {
for (uint i = 0; i < tokenIds.length; i++) {
aavegotchis[i].owner = newOwner;
PolygonXGotchichainBridgeFacet(address(token)).setAavegotchiMetadata(tokenIds[i], aavegotchis[i]);
}
}
}
39 changes: 39 additions & 0 deletions contracts/PolygonXGotchichainBridge/ItemsBridgePolygonSide.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.1;

import {Aavegotchi} from "../Aavegotchi/libraries/LibAppStorage.sol";
import "./ProxyONFT1155.sol";
import "../Aavegotchi/facets/AavegotchiFacet.sol";
import "../Aavegotchi/facets/PolygonXGotchichainBridgeFacet.sol";

contract ItemsBridgePolygonSide is ProxyONFT1155 {
constructor(address _lzEndpoint, address _proxyToken) ProxyONFT1155(_lzEndpoint, _proxyToken) {}

function estimateSendBatchFee(
uint16 _dstChainId,
bytes memory _toAddress,
uint[] memory _tokenIds,
uint[] memory _amounts,
bool _useZro,
bytes memory _adapterParams
) public view override returns (uint nativeFee, uint zroFee) {
bytes memory payload = abi.encode(_toAddress, _tokenIds, _amounts);
return lzEndpoint.estimateFees(_dstChainId, address(this), payload, _useZro, _adapterParams);
}

function _debitFrom(address _from, uint16, bytes memory, uint[] memory _tokenIds, uint[] memory _amounts) internal override {
require(_from == _msgSender(), "ItemsBridgePolygonSide: owner is not send caller");
PolygonXGotchichainBridgeFacet(address(token)).removeItemsFromOwner(_from, _tokenIds, _amounts);
}

function _creditTo(uint16, address _toAddress, uint[] memory _tokenIds, uint[] memory _amounts) internal override {
PolygonXGotchichainBridgeFacet(address(token)).addItemsToOwner(_toAddress, _tokenIds, _amounts);
}

function _updateAavegotchiMetadata(address newOwner, uint[] memory tokenIds, Aavegotchi[] memory aavegotchis) internal {
for (uint i = 0; i < tokenIds.length; i++) {
aavegotchis[i].owner = newOwner;
PolygonXGotchichainBridgeFacet(address(token)).setAavegotchiMetadata(tokenIds[i], aavegotchis[i]);
}
}
}
Loading