diff --git a/contracts/Aavegotchi/Diamond.sol b/contracts/Aavegotchi/Diamond.sol new file mode 100644 index 000000000..4376428e3 --- /dev/null +++ b/contracts/Aavegotchi/Diamond.sol @@ -0,0 +1,44 @@ +import {LibDiamond} from "../shared/libraries/LibDiamond.sol"; +import {DiamondCutFacet} from "../shared/facets/DiamondCutFacet.sol"; +import {DiamondLoupeFacet} from "../shared/facets/DiamondLoupeFacet.sol"; +import {OwnershipFacet} from "../shared/facets/OwnershipFacet.sol"; + +contract Diamond { + constructor(address _contractOwner) { + LibDiamond.setContractOwner(_contractOwner); + LibDiamond.addDiamondFunctions(address(new DiamondCutFacet()), address(new DiamondLoupeFacet()), address(new OwnershipFacet())); + } + + //an immutable function that returns the diamondCut, diamondLoupe, and ownership facet addresses for testing + + function getDefaultFacetAddresses() public view returns (address diamondCut, address diamondLoupe, address ownership) { + LibDiamond.DiamondStorage storage ds = LibDiamond.diamondStorage(); + diamondCut = ds.facetAddresses[0]; + diamondLoupe = ds.facetAddresses[1]; + ownership = ds.facetAddresses[2]; + } + + // Find facet for function that is called and execute the + // function if a facet is found and return any value. + fallback() external payable { + LibDiamond.DiamondStorage storage ds; + bytes32 position = LibDiamond.DIAMOND_STORAGE_POSITION; + assembly { + ds.slot := position + } + address facet = ds.selectorToFacetAndPosition[msg.sig].facetAddress; + require(facet != address(0), "Diamond: Function does not exist"); + assembly { + calldatacopy(0, 0, calldatasize()) + let result := delegatecall(gas(), facet, 0, calldatasize(), 0, 0) + returndatacopy(0, 0, returndatasize()) + switch result + case 0 { + revert(0, returndatasize()) + } + default { + return(0, returndatasize()) + } + } + } +} diff --git a/contracts/Aavegotchi/ForgeDiamond/ForgeDiamond.sol b/contracts/Aavegotchi/ForgeDiamond/ForgeDiamond.sol index e6d51891a..98bd227b2 100644 --- a/contracts/Aavegotchi/ForgeDiamond/ForgeDiamond.sol +++ b/contracts/Aavegotchi/ForgeDiamond/ForgeDiamond.sol @@ -17,11 +17,15 @@ contract ForgeDiamond { address _contractOwner, address _diamondCutFacet, address _diaomondLoupeFacet, - address _ownershipFacet + address _ownershipFacet, + address _aavegotchiDiamond, + address wearableDiamond ) { ForgeLibDiamond.setContractOwner(_contractOwner); ForgeLibDiamond.addDiamondFunctions(_diamondCutFacet, _diaomondLoupeFacet, _ownershipFacet); ForgeLibDiamond.DiamondStorage storage ds = ForgeLibDiamond.diamondStorage(); + ds.AAVEGOTCHI_DIAMOND = _aavegotchiDiamond; + ds.WEARABLE_DIAMOND = wearableDiamond; ds.supportedInterfaces[0xd9b67a26] = true; //erc1155 } diff --git a/contracts/Aavegotchi/ForgeDiamond/facets/ForgeFacet.sol b/contracts/Aavegotchi/ForgeDiamond/facets/ForgeFacet.sol index 29991412f..309e8ca40 100644 --- a/contracts/Aavegotchi/ForgeDiamond/facets/ForgeFacet.sol +++ b/contracts/Aavegotchi/ForgeDiamond/facets/ForgeFacet.sol @@ -46,24 +46,24 @@ contract ForgeFacet is Modifiers { } // External contracts - function aavegotchiGameFacet() internal pure returns (AavegotchiGameFacet facet) { - facet = AavegotchiGameFacet(ForgeLibDiamond.AAVEGOTCHI_DIAMOND); + function aavegotchiGameFacet() internal view returns (AavegotchiGameFacet facet) { + facet = AavegotchiGameFacet(ForgeLibDiamond.AAVEGOTCHI_DIAMOND()); } - function aavegotchiFacet() internal pure returns (AavegotchiFacet facet) { - facet = AavegotchiFacet(ForgeLibDiamond.AAVEGOTCHI_DIAMOND); + function aavegotchiFacet() internal view returns (AavegotchiFacet facet) { + facet = AavegotchiFacet(ForgeLibDiamond.AAVEGOTCHI_DIAMOND()); } - function itemsFacet() internal pure returns (ItemsFacet facet) { - facet = ItemsFacet(ForgeLibDiamond.AAVEGOTCHI_DIAMOND); + function itemsFacet() internal view returns (ItemsFacet facet) { + facet = ItemsFacet(ForgeLibDiamond.AAVEGOTCHI_DIAMOND()); } - function wearablesFacet() internal pure returns (WearablesFacet facet) { - facet = WearablesFacet(ForgeLibDiamond.WEARABLE_DIAMOND); + function wearablesFacet() internal view returns (WearablesFacet facet) { + facet = WearablesFacet(ForgeLibDiamond.WEARABLE_DIAMOND()); } - function lendingGetterAndSetterFacet() internal pure returns (LendingGetterAndSetterFacet facet) { - facet = LendingGetterAndSetterFacet(ForgeLibDiamond.AAVEGOTCHI_DIAMOND); + function lendingGetterAndSetterFacet() internal view returns (LendingGetterAndSetterFacet facet) { + facet = LendingGetterAndSetterFacet(ForgeLibDiamond.AAVEGOTCHI_DIAMOND()); } function gltrContract() internal view returns (IERC20 token) { @@ -288,11 +288,7 @@ contract ForgeFacet is Modifiers { } } - function _forge( - uint256 itemId, - uint256 gotchiId, - uint40 _gltr - ) internal onlyAavegotchiOwner(gotchiId) onlyAavegotchiUnlocked(gotchiId) { + function _forge(uint256 itemId, uint256 gotchiId, uint40 _gltr) internal onlyAavegotchiOwner(gotchiId) onlyAavegotchiUnlocked(gotchiId) { require(!s.gotchiForging[gotchiId].isForging, "ForgeFacet: Aavegotchi already forging"); address sender = LibMeta.msgSender(); @@ -403,7 +399,7 @@ contract ForgeFacet is Modifiers { uint40 blockLeft = queueItem.readyBlock - uint40(block.number); uint40 removeBlocks = _amounts[i] <= blockLeft ? _amounts[i] : blockLeft; - uint256 burnAmount = uint256(removeBlocks) * 10**18; + uint256 burnAmount = uint256(removeBlocks) * 10 ** 18; require( gltrContract().transferFrom(msg.sender, 0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF, burnAmount), @@ -451,11 +447,7 @@ contract ForgeFacet is Modifiers { } } - function forgeWearables( - uint256[] calldata _itemIds, - uint256[] calldata _gotchiIds, - uint40[] calldata _gltr - ) external whenNotPaused { + function forgeWearables(uint256[] calldata _itemIds, uint256[] calldata _gotchiIds, uint40[] calldata _gltr) external whenNotPaused { require(_itemIds.length == _gotchiIds.length && _gotchiIds.length == _gltr.length, "ForgeFacet: mismatched array lengths"); for (uint256 i; i < _itemIds.length; i++) { @@ -475,10 +467,8 @@ contract ForgeFacet is Modifiers { // @notice Allow Aavegotchi diamond to mint essence. // @dev Only called from CollateralFacet's decreaseAndDestroy function. Not including a whenNotPaused modifier // here to avoid impacts to aavegotchi sacrifice functionality. - function mintEssence( - address owner /*uint256 gotchiId*/ - ) external { - require(LibMeta.msgSender() == ForgeLibDiamond.AAVEGOTCHI_DIAMOND, "ForgeFacet: Can only be called by Aavegotchi Diamond"); + function mintEssence(address owner /*uint256 gotchiId*/) external { + require(LibMeta.msgSender() == ForgeLibDiamond.AAVEGOTCHI_DIAMOND(), "ForgeFacet: Can only be called by Aavegotchi Diamond"); // require(aavegotchiFacet.ownerOf(gotchiId) == address(0), "ForgeFacet: Aavegotchi not sacrificed"); _mintItem(owner, ESSENCE, 1000); @@ -522,41 +512,25 @@ contract ForgeFacet is Modifiers { } } - function _mintItem( - address account, - uint256 id, - uint256 amount - ) internal { + function _mintItem(address account, uint256 id, uint256 amount) internal { // mint doesnt exceed max supply // require(totalSupply(id) + amount <= s.maxSupplyByToken[id], "ForgeFacet: mint would exceed max supply"); _mint(account, id, amount); } - function adminMint( - address account, - uint256 id, - uint256 amount - ) external onlyDaoOrOwner { + function adminMint(address account, uint256 id, uint256 amount) external onlyDaoOrOwner { // mint doesnt exceed max supply // require(totalSupply(id) + amount <= s.maxSupplyByToken[id], "ForgeFacet: mint would exceed max supply"); _mint(account, id, amount); } - function adminMintBatch( - address to, - uint256[] memory ids, - uint256[] memory amounts - ) external onlyDaoOrOwner { + function adminMintBatch(address to, uint256[] memory ids, uint256[] memory amounts) external onlyDaoOrOwner { // mint doesnt exceed max supply // require(totalSupply(id) + amount <= s.maxSupplyByToken[id], "ForgeFacet: mint would exceed max supply"); _mintBatch(to, ids, amounts); } - function burn( - address account, - uint256 id, - uint256 amount - ) external { + function burn(address account, uint256 id, uint256 amount) external { require( account == msg.sender || forgeTokenFacet().isApprovedForAll(account, msg.sender), "ForgeFacet: caller is not token owner or approved" @@ -568,11 +542,7 @@ contract ForgeFacet is Modifiers { // function _mintBatchItems(address to, uint256[] memory ids, uint256[] memory amounts) internal { // _mintBatch(to, ids, amounts, ""); // } - function _burnItem( - address account, - uint256 id, - uint256 amount - ) internal { + function _burnItem(address account, uint256 id, uint256 amount) internal { _burn(account, id, amount); } @@ -604,11 +574,7 @@ contract ForgeFacet is Modifiers { emit TransferBatch(msg.sender, address(0), to, ids, amounts); } - function _burn( - address from, - uint256 id, - uint256 amount - ) internal virtual { + function _burn(address from, uint256 id, uint256 amount) internal virtual { require(from != address(0), "ForgeTokenFacet: burn from the zero address"); uint256 fromBalance = s._balances[id][from]; @@ -621,11 +587,7 @@ contract ForgeFacet is Modifiers { emit TransferSingle(msg.sender, from, address(0), id, amount); } - function _burnBatch( - address from, - uint256[] memory ids, - uint256[] memory amounts - ) internal virtual { + function _burnBatch(address from, uint256[] memory ids, uint256[] memory amounts) internal virtual { require(from != address(0), "ForgeTokenFacet: burn from the zero address"); require(ids.length == amounts.length, "ForgeTokenFacet: ids and amounts length mismatch"); diff --git a/contracts/Aavegotchi/ForgeDiamond/facets/ForgeVRFFacet.sol b/contracts/Aavegotchi/ForgeDiamond/facets/ForgeVRFFacet.sol index 3cf1c8a68..8ac490d8e 100644 --- a/contracts/Aavegotchi/ForgeDiamond/facets/ForgeVRFFacet.sol +++ b/contracts/Aavegotchi/ForgeDiamond/facets/ForgeVRFFacet.sol @@ -8,8 +8,6 @@ import {ILink} from "../../interfaces/ILink.sol"; import {ForgeFacet} from "./ForgeFacet.sol"; import {ForgeTokenFacet} from "./ForgeTokenFacet.sol"; - - contract ForgeVRFFacet is Modifiers { event VrfResponse(address user, uint256 randomNumber, bytes32 requestId, uint256 blockNumber); event GeodeWin(address user, uint256 itemId, uint256 geodeTokenId, bytes32 requestId, uint256 blockNumber); @@ -116,7 +114,7 @@ contract ForgeVRFFacet is Modifiers { s.vrfUserToRequestIds[sender].push(requestId); // for testing - // tempFulfillRandomness(requestId, uint256(keccak256(abi.encodePacked(block.number, _geodeTokenIds[0])))); + // tempFulfillRandomness(requestId, uint256(keccak256(abi.encodePacked(block.number, _geodeTokenIds[0])))); } // for testing purpose only @@ -325,13 +323,11 @@ contract ForgeVRFFacet is Modifiers { if (data.rarityWonIndex >= 0) { data.prizes = getAvailablePrizesForRarity(rarities[uint(data.rarityWonIndex)]); - - uint256 idx = data.geodeRandNum % data.prizes.length; data.itemIdWon = data.prizes[idx]; - + // if last quantity of item won, rearrange array. if (s.geodePrizeQuantities[data.itemIdWon] == 1) { // find index in geodePrizeTokenIds @@ -342,14 +338,11 @@ contract ForgeVRFFacet is Modifiers { break; } } - s.geodePrizeTokenIds[tokenIdsIndex] = s.geodePrizeTokenIds[s.geodePrizeTokenIds.length - 1]; s.geodePrizeTokenIds.pop(); } - - s.geodePrizeQuantities[data.itemIdWon] -= 1; data.numWins++; @@ -358,8 +351,6 @@ contract ForgeVRFFacet is Modifiers { emit GeodeWin(sender, data.itemIdWon, info.geodeTokenIds[i], requestId, block.number); } else { - - forgeFacet().burn(address(this), info.geodeTokenIds[i], 1); emit GeodeEmpty(sender, info.geodeTokenIds[i], requestId, block.number); } diff --git a/contracts/Aavegotchi/ForgeDiamond/libraries/ForgeLibDiamond.sol b/contracts/Aavegotchi/ForgeDiamond/libraries/ForgeLibDiamond.sol index cc45bb049..aec0068f9 100644 --- a/contracts/Aavegotchi/ForgeDiamond/libraries/ForgeLibDiamond.sol +++ b/contracts/Aavegotchi/ForgeDiamond/libraries/ForgeLibDiamond.sol @@ -37,12 +37,14 @@ library ForgeLibDiamond { // owner of the contract address contractOwner; //aavegotchi master diamond address - address aavegotchiDiamond; + address AAVEGOTCHI_DIAMOND; + //aavegotchi wearable diamond address + address WEARABLE_DIAMOND; } bytes32 public constant DIAMOND_STORAGE_POSITION = keccak256("diamond.standard.diamond.storage"); - address public constant AAVEGOTCHI_DIAMOND = 0x86935F11C86623deC8a25696E1C19a8659CbF95d; - address public constant WEARABLE_DIAMOND = 0x58de9AaBCaeEC0f69883C94318810ad79Cc6a44f; + // address public constant AAVEGOTCHI_DIAMOND = 0x86935F11C86623deC8a25696E1C19a8659CbF95d; + // address public constant WEARABLE_DIAMOND = 0x58de9AaBCaeEC0f69883C94318810ad79Cc6a44f; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); @@ -60,6 +62,14 @@ library ForgeLibDiamond { emit OwnershipTransferred(previousOwner, _newOwner); } + function WEARABLE_DIAMOND() internal view returns (address wearableDiamond_) { + wearableDiamond_ = diamondStorage().WEARABLE_DIAMOND; + } + + function AAVEGOTCHI_DIAMOND() internal view returns (address aavegotchiDiamond_) { + aavegotchiDiamond_ = diamondStorage().AAVEGOTCHI_DIAMOND; + } + function contractOwner() internal view returns (address contractOwner_) { contractOwner_ = diamondStorage().contractOwner; } @@ -69,16 +79,12 @@ library ForgeLibDiamond { } function enforceIsDiamond() internal view { - require(msg.sender == AAVEGOTCHI_DIAMOND, "LibDiamond: Caller must be Aavegotchi Diamond"); + require(msg.sender == AAVEGOTCHI_DIAMOND(), "LibDiamond: Caller must be Aavegotchi Diamond"); } event DiamondCut(IDiamondCut.FacetCut[] _diamondCut, address _init, bytes _calldata); - function addDiamondFunctions( - address _diamondCutFacet, - address _diamondLoupeFacet, - address _ownershipFacet - ) internal { + function addDiamondFunctions(address _diamondCutFacet, address _diamondLoupeFacet, address _ownershipFacet) internal { IDiamondCut.FacetCut[] memory cut = new IDiamondCut.FacetCut[](3); bytes4[] memory functionSelectors = new bytes4[](1); functionSelectors[0] = IDiamondCut.diamondCut.selector; @@ -102,11 +108,7 @@ library ForgeLibDiamond { } // Internal function version of diamondCut - function diamondCut( - IDiamondCut.FacetCut[] memory _diamondCut, - address _init, - bytes memory _calldata - ) internal { + function diamondCut(IDiamondCut.FacetCut[] memory _diamondCut, address _init, bytes memory _calldata) internal { for (uint256 facetIndex; facetIndex < _diamondCut.length; facetIndex++) { IDiamondCut.FacetCutAction action = _diamondCut[facetIndex].action; if (action == IDiamondCut.FacetCutAction.Add) { diff --git a/contracts/Aavegotchi/ForgeDiamond/libraries/LibAppStorage.sol b/contracts/Aavegotchi/ForgeDiamond/libraries/LibAppStorage.sol index 0e0e1c27b..15a4ee573 100644 --- a/contracts/Aavegotchi/ForgeDiamond/libraries/LibAppStorage.sol +++ b/contracts/Aavegotchi/ForgeDiamond/libraries/LibAppStorage.sol @@ -168,7 +168,6 @@ struct AppStorage { mapping(uint8 => uint256) forgeTimeCostInBlocks; // Map rarity score modifier (which denotes item rarity) to number of skill points earned for successful forging. mapping(uint8 => uint256) skillPointsEarnedFromForge; - // Map rarity score modifier (which denotes item rarity) to percent chance (in bips) to win a prize. /**** NOTE: Deprecated *****/ mapping(uint8 => uint256) geodeWinChanceBips; @@ -190,7 +189,6 @@ struct AppStorage { address vrfCoordinator; bytes32 keyHash; uint144 vrfFee; - mapping(uint8 => mapping(uint8 => uint256)) geodeWinChanceMultiTierBips; mapping(uint256 => uint8) geodePrizeRarities; } diff --git a/contracts/Aavegotchi/InitDiamond.sol b/contracts/Aavegotchi/InitDiamond.sol index 4e2cb2fb9..79a07281e 100644 --- a/contracts/Aavegotchi/InitDiamond.sol +++ b/contracts/Aavegotchi/InitDiamond.sol @@ -20,9 +20,8 @@ contract InitDiamond { address rarityFarming; address ghstContract; bytes32 chainlinkKeyHash; - uint256 chainlinkFee; + uint64 subscriptionId; address vrfCoordinator; - address linkAddress; address childChainManager; string name; string symbol; @@ -48,9 +47,8 @@ contract InitDiamond { s.ghstContract = _args.ghstContract; s.keyHash = _args.chainlinkKeyHash; - s.fee = uint144(_args.chainlinkFee); + s.subscriptionId = (_args.subscriptionId); s.vrfCoordinator = _args.vrfCoordinator; - s.link = ILink(_args.linkAddress); s.listingFeeInWei = 1e17; diff --git a/contracts/Aavegotchi/WearableDiamond/WearableDiamond.sol b/contracts/Aavegotchi/WearableDiamond/WearableDiamond.sol index 02529c5d4..7d9f99702 100644 --- a/contracts/Aavegotchi/WearableDiamond/WearableDiamond.sol +++ b/contracts/Aavegotchi/WearableDiamond/WearableDiamond.sol @@ -13,15 +13,11 @@ import {DiamondLoupeFacet} from "../../shared/facets/DiamondLoupeFacet.sol"; import {OwnershipFacet} from "../../shared/facets/OwnershipFacet.sol"; contract WearableDiamond { - constructor( - address _contractOwner, - address _diamondCutFacet, - address _diaomondLoupeFacet, - address _ownershipFacet - ) { + constructor(address _contractOwner, address _diamondCutFacet, address _diaomondLoupeFacet, address _ownershipFacet, address aavegotchiDiamond) { WearableLibDiamond.setContractOwner(_contractOwner); WearableLibDiamond.addDiamondFunctions(_diamondCutFacet, _diaomondLoupeFacet, _ownershipFacet); WearableLibDiamond.DiamondStorage storage ds = WearableLibDiamond.diamondStorage(); + ds.AAVEGOTCHI_DIAMOND = aavegotchiDiamond; ds.supportedInterfaces[0xd9b67a26] = true; //erc1155 } diff --git a/contracts/Aavegotchi/WearableDiamond/facets/WearablesFacet.sol b/contracts/Aavegotchi/WearableDiamond/facets/WearablesFacet.sol index c4c73f350..fcd13f07a 100644 --- a/contracts/Aavegotchi/WearableDiamond/facets/WearablesFacet.sol +++ b/contracts/Aavegotchi/WearableDiamond/facets/WearablesFacet.sol @@ -9,16 +9,16 @@ import {ItemsFacet} from "../../facets/ItemsFacet.sol"; import {AavegotchiFacet} from "../../facets/AavegotchiFacet.sol"; contract WearablesFacet { - function periphery() internal pure returns (PeripheryFacet pFacet) { - pFacet = PeripheryFacet(WearableLibDiamond.AAVEGOTCHI_DIAMOND); + function periphery() internal view returns (PeripheryFacet pFacet) { + pFacet = PeripheryFacet(WearableLibDiamond.AAVEGOTCHI_DIAMOND()); } - function itemsFacet() internal pure returns (ItemsFacet iFacet) { - iFacet = ItemsFacet(WearableLibDiamond.AAVEGOTCHI_DIAMOND); + function itemsFacet() internal view returns (ItemsFacet iFacet) { + iFacet = ItemsFacet(WearableLibDiamond.AAVEGOTCHI_DIAMOND()); } - function aavegotchiFacet() internal pure returns (AavegotchiFacet aFacet) { - aFacet = AavegotchiFacet(WearableLibDiamond.AAVEGOTCHI_DIAMOND); + function aavegotchiFacet() internal view returns (AavegotchiFacet aFacet) { + aFacet = AavegotchiFacet(WearableLibDiamond.AAVEGOTCHI_DIAMOND()); } //READ @@ -39,7 +39,7 @@ contract WearablesFacet { approved_ = aavegotchiFacet().isApprovedForAll(_owner, _operator); } - function tokenURI(uint256 _tokenId) external pure returns (string memory) { + function tokenURI(uint256 _tokenId) external view returns (string memory) { return aavegotchiFacet().tokenURI(_tokenId); } @@ -65,25 +65,13 @@ contract WearablesFacet { } } - function safeTransferFrom( - address _from, - address _to, - uint256 _id, - uint256 _value, - bytes calldata _data - ) external { + function safeTransferFrom(address _from, address _to, uint256 _id, uint256 _value, bytes calldata _data) external { periphery().peripherySafeTransferFrom(msg.sender, _from, _to, _id, _value, _data); //emit event LibEventHandler._receiveAndEmitTransferSingleEvent(msg.sender, _from, _to, _id, _value); } - function safeBatchTransferFrom( - address _from, - address _to, - uint256[] calldata _ids, - uint256[] calldata _values, - bytes calldata _data - ) external { + function safeBatchTransferFrom(address _from, address _to, uint256[] calldata _ids, uint256[] calldata _values, bytes calldata _data) external { periphery().peripherySafeBatchTransferFrom(msg.sender, _from, _to, _ids, _values, _data); //emit event LibEventHandler._receiveAndEmitTransferBatchEvent(msg.sender, _from, _to, _ids, _values); diff --git a/contracts/Aavegotchi/WearableDiamond/libraries/WearableLibDiamond.sol b/contracts/Aavegotchi/WearableDiamond/libraries/WearableLibDiamond.sol index ceb24320e..5f0ac9049 100644 --- a/contracts/Aavegotchi/WearableDiamond/libraries/WearableLibDiamond.sol +++ b/contracts/Aavegotchi/WearableDiamond/libraries/WearableLibDiamond.sol @@ -14,7 +14,7 @@ import {LibMeta} from "../../../shared/libraries/LibMeta.sol"; library WearableLibDiamond { bytes32 constant DIAMOND_STORAGE_POSITION = keccak256("diamond.standard.diamond.storage"); - address constant AAVEGOTCHI_DIAMOND = 0x86935F11C86623deC8a25696E1C19a8659CbF95d; + // address constant AAVEGOTCHI_DIAMOND = 0x86935F11C86623deC8a25696E1C19a8659CbF95d; struct FacetAddressAndPosition { address facetAddress; @@ -40,7 +40,7 @@ library WearableLibDiamond { // owner of the contract address contractOwner; //aavegotchi master diamond address - address aavegotchiDiamond; + address AAVEGOTCHI_DIAMOND; } function diamondStorage() internal pure returns (DiamondStorage storage ds) { @@ -50,6 +50,10 @@ library WearableLibDiamond { } } + function AAVEGOTCHI_DIAMOND() internal view returns (address) { + return diamondStorage().AAVEGOTCHI_DIAMOND; + } + event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); function setContractOwner(address _newOwner) internal { @@ -68,16 +72,12 @@ library WearableLibDiamond { } function enforceIsDiamond() internal view { - require(msg.sender == AAVEGOTCHI_DIAMOND, "LibDiamond: Caller must be Aavegotchi Diamond"); + require(msg.sender == diamondStorage().AAVEGOTCHI_DIAMOND, "LibDiamond: Caller must be Aavegotchi Diamond"); } event DiamondCut(IDiamondCut.FacetCut[] _diamondCut, address _init, bytes _calldata); - function addDiamondFunctions( - address _diamondCutFacet, - address _diamondLoupeFacet, - address _ownershipFacet - ) internal { + function addDiamondFunctions(address _diamondCutFacet, address _diamondLoupeFacet, address _ownershipFacet) internal { IDiamondCut.FacetCut[] memory cut = new IDiamondCut.FacetCut[](3); bytes4[] memory functionSelectors = new bytes4[](1); functionSelectors[0] = IDiamondCut.diamondCut.selector; @@ -101,11 +101,7 @@ library WearableLibDiamond { } // Internal function version of diamondCut - function diamondCut( - IDiamondCut.FacetCut[] memory _diamondCut, - address _init, - bytes memory _calldata - ) internal { + function diamondCut(IDiamondCut.FacetCut[] memory _diamondCut, address _init, bytes memory _calldata) internal { for (uint256 facetIndex; facetIndex < _diamondCut.length; facetIndex++) { IDiamondCut.FacetCutAction action = _diamondCut[facetIndex].action; if (action == IDiamondCut.FacetCutAction.Add) { diff --git a/contracts/Aavegotchi/facets/AavegotchiGameFacet.sol b/contracts/Aavegotchi/facets/AavegotchiGameFacet.sol index a2d6a3c26..ba0fbf10f 100644 --- a/contracts/Aavegotchi/facets/AavegotchiGameFacet.sol +++ b/contracts/Aavegotchi/facets/AavegotchiGameFacet.sol @@ -230,7 +230,11 @@ contract AavegotchiGameFacet is Modifiers { ///@param _tokenId The identifier of NFT to claim an Aavegotchi from ///@param _option The index of the aavegotchi to claim(1-10) ///@param _stakeAmount Minimum amount of collateral tokens needed to be sent to the new aavegotchi escrow contract - function claimAavegotchi(uint256 _tokenId, uint256 _option, uint256 _stakeAmount) external onlyUnlocked(_tokenId) onlyAavegotchiOwner(_tokenId) { + function claimAavegotchi( + uint256 _tokenId, + uint256 _option, + uint256 _stakeAmount + ) external onlyUnlocked(_tokenId) onlyAavegotchiOwner(_tokenId) { Aavegotchi storage aavegotchi = s.aavegotchis[_tokenId]; require(aavegotchi.status == LibAavegotchi.STATUS_OPEN_PORTAL, "AavegotchiGameFacet: Portal not open"); require(_option < PORTAL_AAVEGOTCHIS_NUM, "AavegotchiGameFacet: Only 10 aavegotchi options available"); diff --git a/contracts/Aavegotchi/facets/DAOFacet.sol b/contracts/Aavegotchi/facets/DAOFacet.sol index 776670494..e83c4aa5a 100644 --- a/contracts/Aavegotchi/facets/DAOFacet.sol +++ b/contracts/Aavegotchi/facets/DAOFacet.sol @@ -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 GotchiGeistBridgeUpdate(address _newBridge); + event ItemGeistBridgeUpdate(address _newBridge); /***********************************| | Read Functions | @@ -99,7 +101,11 @@ contract DAOFacet is Modifiers { //First handle global collateralTypes array uint256 index = s.collateralTypeIndexes[newCollateralType]; - bool collateralExists = index > 0 || s.collateralTypes[0] == newCollateralType; + bool collateralExists = index > 0; + + if (!collateralExists && s.collateralTypes.length == 1 && s.collateralTypes[0] == newCollateralType) { + collateralExists = true; + } if (!collateralExists) { s.collateralTypes.push(newCollateralType); @@ -174,7 +180,11 @@ contract DAOFacet is Modifiers { ///@param _hauntMaxSize The maximum number of portals in the new haunt ///@param _portalPrice The base price of portals in the new haunt(in $GHST) ///@param _bodyColor The universal body color applied to NFTs in the new haunt - function createHaunt(uint24 _hauntMaxSize, uint96 _portalPrice, bytes3 _bodyColor) external onlyDaoOrOwner returns (uint256 hauntId_) { + function createHaunt( + uint24 _hauntMaxSize, + uint96 _portalPrice, + bytes3 _bodyColor + ) external onlyDaoOrOwner returns (uint256 hauntId_) { uint256 currentHauntId = s.currentHauntId; require( s.haunts[currentHauntId].totalCount == s.haunts[currentHauntId].hauntMaxSize, @@ -425,4 +435,18 @@ contract DAOFacet is Modifiers { emit UpdateItemPrice(itemId, _newPrices[i]); } } + + ///@notice Allow the DAO to update an address as a Geist bridge of the gotchi + ///@param _newBridge The address to be update as a bridge + function updateGotchiGeistBridge(address _newBridge) external onlyDaoOrOwner { + s.gotchGeistBridge = _newBridge; + emit GotchiGeistBridgeUpdate(_newBridge); + } + + ///@notice Allow the DAO to update an address as a Geist bridge of the item + ///@param _newBridge The address to be update as a bridge + function updateItemGeistBridge(address _newBridge) external onlyDaoOrOwner { + s.itemGeistBridge = _newBridge; + emit ItemGeistBridgeUpdate(_newBridge); + } } diff --git a/contracts/Aavegotchi/facets/ItemsRolesRegistryFacet.sol b/contracts/Aavegotchi/facets/ItemsRolesRegistryFacet.sol index df09d2539..942331250 100644 --- a/contracts/Aavegotchi/facets/ItemsRolesRegistryFacet.sol +++ b/contracts/Aavegotchi/facets/ItemsRolesRegistryFacet.sol @@ -17,7 +17,7 @@ import {LibERC1155} from "../../shared/libraries/LibERC1155.sol"; import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; import {LibItemsEvents} from "../libraries/LibItemsEvents.sol"; -contract ItemsRolesRegistryFacet is Modifiers, IERC7589, ERC1155Holder { +contract ItemsRolesRegistryFacet is Modifiers, IERC7589 { using EnumerableSet for EnumerableSet.UintSet; bytes32 public constant UNIQUE_ROLE = keccak256("Player()"); diff --git a/contracts/Aavegotchi/facets/PolygonXGeistBridgeFacet.sol b/contracts/Aavegotchi/facets/PolygonXGeistBridgeFacet.sol new file mode 100644 index 000000000..c3f7b47bf --- /dev/null +++ b/contracts/Aavegotchi/facets/PolygonXGeistBridgeFacet.sol @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.1; + +import {Aavegotchi, Modifiers} from "../libraries/LibAppStorage.sol"; +import {LibAavegotchi} from "../libraries/LibAavegotchi.sol"; +import {LibItems} from "../libraries/LibItems.sol"; +import {LibERC721} from "../../shared/libraries/LibERC721.sol"; +import {LibERC1155} from "../../shared/libraries/LibERC1155.sol"; +import {INFTBridge} from "../../shared/interfaces/INFTBridge.sol"; +import {LibERC20} from "../../shared/libraries/LibERC20.sol"; +import {IERC20} from "../../shared/interfaces/IERC20.sol"; +import "../WearableDiamond/interfaces/IEventHandlerFacet.sol"; + +contract PolygonXGeistBridgeFacet is Modifiers { + + function bridgeGotchi( + address _receiver, + uint256 _tokenId, + uint256 _msgGasLimit, + address _connector + ) external payable { + Aavegotchi memory _aavegotchi = s.aavegotchis[_tokenId]; + // force unstake from escrow + uint256 currentStake = IERC20(_aavegotchi.collateralType).balanceOf(_aavegotchi.escrow); + LibERC20.transferFrom(_aavegotchi.collateralType, _aavegotchi.escrow, msg.sender, currentStake); + + bytes memory _metadata = abi.encode(_aavegotchi); + INFTBridge(s.gotchGeistBridge).bridge(_receiver, msg.sender, _tokenId, 1, _msgGasLimit, _connector, _metadata, new bytes(0)); + for (uint slot; slot < _aavegotchi.equippedWearables.length; slot++) { + uint wearableId = _aavegotchi.equippedWearables[slot]; + if (wearableId != 0) { + delete s.aavegotchis[_tokenId].equippedWearables[slot]; + LibItems.removeFromParent(address(this), _tokenId, wearableId, 1); + LibItems.addToOwner(s.itemGeistBridge, wearableId, 1); + IEventHandlerFacet(s.wearableDiamond).emitTransferSingleEvent(msg.sender, address(this), s.itemGeistBridge, wearableId, 1); + emit LibERC1155.TransferFromParent(address(this), _tokenId, wearableId, 1); + } + } + } + + function setMetadata(uint _tokenId, bytes memory _metadata) external onlyGotchiGeistBridge { + Aavegotchi memory _aavegotchi = abi.decode(_metadata, (Aavegotchi)); + s.aavegotchis[_tokenId] = _aavegotchi; + + for (uint slot; slot < _aavegotchi.equippedWearables.length; slot++) { + if (_aavegotchi.equippedWearables[slot] != 0) { + uint wearableId = _aavegotchi.equippedWearables[slot]; + LibItems.removeFromOwner(s.itemGeistBridge, wearableId, 1); + IEventHandlerFacet(s.wearableDiamond).emitTransferSingleEvent(msg.sender, s.itemGeistBridge, address(this), wearableId, 1); + LibItems.addToParent(address(this), _tokenId, wearableId, 1); + emit LibERC1155.TransferToParent(address(this), _tokenId, wearableId, 1); + } + } + } + + function bridgeItem( + address _receiver, + uint256 _tokenId, + uint256 _amount, + uint256 _msgGasLimit, + address _connector + ) external payable { + INFTBridge(s.itemGeistBridge).bridge(_receiver, msg.sender, _tokenId, _amount, _msgGasLimit, _connector, new bytes(0), new bytes(0)); + } +} diff --git a/contracts/Aavegotchi/facets/VRFFacet.sol b/contracts/Aavegotchi/facets/VRFFacet.sol index 08b93c645..c3f1223c1 100644 --- a/contracts/Aavegotchi/facets/VRFFacet.sol +++ b/contracts/Aavegotchi/facets/VRFFacet.sol @@ -6,6 +6,8 @@ import {LibMeta} from "../../shared/libraries/LibMeta.sol"; import {LibERC721Marketplace} from "../libraries/LibERC721Marketplace.sol"; import {LibAavegotchi} from "../libraries/LibAavegotchi.sol"; import {ILink} from "../interfaces/ILink.sol"; +import {VRFCoordinatorV2Interface} from "../interfaces/VRFCoordinatorV2Interface.sol"; +import {REQUEST_CONFIRMATIONS, NO_OF_WORDS, VRF_GAS_LIMIT} from "../libraries/LibAppStorage.sol"; //import "hardhat/console.sol"; @@ -92,17 +94,17 @@ contract VrfFacet is Modifiers { | Read Functions | |__________________________________*/ - function linkBalance() external view returns (uint256 linkBalance_) { - linkBalance_ = s.link.balanceOf(address(this)); - } + // function linkBalance() external view returns (uint256 linkBalance_) { + // linkBalance_ = s.link.balanceOf(address(this)); + // } function vrfCoordinator() external view returns (address) { return s.vrfCoordinator; } - function link() external view returns (address) { - return address(s.link); - } + // function link() external view returns (address) { + // return address(s.link); + // } function keyHash() external view returns (bytes32) { return s.keyHash; @@ -131,22 +133,22 @@ contract VrfFacet is Modifiers { emit OpenPortals(_tokenIds); } - function drawRandomNumber(uint256 _tokenId) internal { + function drawRandomNumber(uint256 _tokenId) internal returns (uint256 requestId_) { s.aavegotchis[_tokenId].status = LibAavegotchi.STATUS_VRF_PENDING; - uint256 fee = s.fee; - require(s.link.balanceOf(address(this)) >= fee, "VrfFacet: Not enough LINK"); - bytes32 l_keyHash = s.keyHash; - require(s.link.transferAndCall(s.vrfCoordinator, fee, abi.encode(l_keyHash, 0)), "VrfFacet: link transfer failed"); - uint256 vrfSeed = uint256(keccak256(abi.encode(l_keyHash, 0, address(this), s.vrfNonces[l_keyHash]))); - s.vrfNonces[l_keyHash]++; - bytes32 requestId = keccak256(abi.encodePacked(l_keyHash, vrfSeed)); - s.vrfRequestIdToTokenId[requestId] = _tokenId; + requestId_ = VRFCoordinatorV2Interface(s.vrfCoordinator).requestRandomWords( + s.keyHash, + s.subscriptionId, + REQUEST_CONFIRMATIONS, + VRF_GAS_LIMIT, + NO_OF_WORDS + ); + s.vrfRequestIdToTokenId[requestId_] = _tokenId; // for testing - tempFulfillRandomness(requestId, uint256(keccak256(abi.encodePacked(block.number, _tokenId)))); + // tempFulfillRandomness(requestId_, uint256(keccak256(abi.encodePacked(block.number, _tokenId)))); } // for testing purpose only - function tempFulfillRandomness(bytes32 _requestId, uint256 _randomNumber) internal { + function tempFulfillRandomness(uint256 _requestId, uint256 _randomNumber) internal { // console.log("bytes"); // console.logBytes32(_requestId); //_requestId; // mentioned here to remove unused variable warning @@ -174,19 +176,18 @@ contract VrfFacet is Modifiers { * @dev rawFulfillRandomness, below.) * * @param _requestId The Id initially returned by requestRandomness - * @param _randomNumber the VRF output + * @param _randomWords the VRF output */ - function rawFulfillRandomness(bytes32 _requestId, uint256 _randomNumber) external { - uint256 tokenId = s.vrfRequestIdToTokenId[_requestId]; - + function rawFulfillRandomWords(uint256 _requestId, uint256[] memory _randomWords) external { require(LibMeta.msgSender() == s.vrfCoordinator, "Only VRFCoordinator can fulfill"); - + uint256 tokenId = s.vrfRequestIdToTokenId[_requestId]; require(s.aavegotchis[tokenId].status == LibAavegotchi.STATUS_VRF_PENDING, "VrfFacet: VRF is not pending"); + s.aavegotchis[tokenId].status = LibAavegotchi.STATUS_OPEN_PORTAL; - s.tokenIdToRandomNumber[tokenId] = _randomNumber; + s.tokenIdToRandomNumber[tokenId] = _randomWords[0]; emit PortalOpened(tokenId); - emit VrfRandomNumber(tokenId, _randomNumber, block.timestamp); + emit VrfRandomNumber(tokenId, _randomWords[0], block.timestamp); } ///@notice Allow the aavegotchi diamond owner to change the vrf details @@ -194,14 +195,9 @@ contract VrfFacet is Modifiers { //@param _keyHash New keyhash //@param _vrfCoordinator The new vrf coordinator address //@param _link New LINK token contract address - function changeVrf( - uint256 _newFee, - bytes32 _keyHash, - address _vrfCoordinator, - address _link - ) external onlyOwner { - if (_newFee != 0) { - s.fee = uint96(_newFee); + function changeVrf(uint64 _newSubscriptionId, bytes32 _keyHash, address _vrfCoordinator) external onlyOwner { + if (_newSubscriptionId != 0) { + s.subscriptionId = _newSubscriptionId; } if (_keyHash != 0) { s.keyHash = _keyHash; @@ -209,13 +205,13 @@ contract VrfFacet is Modifiers { if (_vrfCoordinator != address(0)) { s.vrfCoordinator = _vrfCoordinator; } - if (_link != address(0)) { - s.link = ILink(_link); - } } - // Remove the LINK tokens from this contract that are used to pay for VRF random number fees - function removeLinkTokens(address _to, uint256 _value) external onlyOwner { - s.link.transfer(_to, _value); + function getVrfInfo() public view returns (uint64, bytes32, address, string memory) { + return (s.subscriptionId, s.keyHash, s.vrfCoordinator, s.name); } + // // Remove the LINK tokens from this contract that are used to pay for VRF random number fees + // function removeLinkTokens(address _to, uint256 _value) external onlyOwner { + // s.link.transfer(_to, _value); + // } } diff --git a/contracts/Aavegotchi/interfaces/VRFCoordinatorV2Interface.sol b/contracts/Aavegotchi/interfaces/VRFCoordinatorV2Interface.sol new file mode 100644 index 000000000..203f8e7bd --- /dev/null +++ b/contracts/Aavegotchi/interfaces/VRFCoordinatorV2Interface.sol @@ -0,0 +1,113 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.1; + +// solhint-disable-next-line interface-starts-with-i +interface VRFCoordinatorV2Interface { + /** + * @notice Get configuration relevant for making requests + * @return minimumRequestConfirmations global min for request confirmations + * @return maxGasLimit global max for request gas limit + * @return s_provingKeyHashes list of registered key hashes + */ + function getRequestConfig() external view returns (uint16, uint32, bytes32[] memory); + + /** + * @notice Request a set of random words. + * @param keyHash - Corresponds to a particular oracle job which uses + * that key for generating the VRF proof. Different keyHash's have different gas price + * ceilings, so you can select a specific one to bound your maximum per request cost. + * @param subId - The ID of the VRF subscription. Must be funded + * with the minimum subscription balance required for the selected keyHash. + * @param minimumRequestConfirmations - How many blocks you'd like the + * oracle to wait before responding to the request. See SECURITY CONSIDERATIONS + * for why you may want to request more. The acceptable range is + * [minimumRequestBlockConfirmations, 200]. + * @param callbackGasLimit - How much gas you'd like to receive in your + * fulfillRandomWords callback. Note that gasleft() inside fulfillRandomWords + * may be slightly less than this amount because of gas used calling the function + * (argument decoding etc.), so you may need to request slightly more than you expect + * to have inside fulfillRandomWords. The acceptable range is + * [0, maxGasLimit] + * @param numWords - The number of uint256 random values you'd like to receive + * in your fulfillRandomWords callback. Note these numbers are expanded in a + * secure way by the VRFCoordinator from a single random value supplied by the oracle. + * @return requestId - A unique identifier of the request. Can be used to match + * a request to a response in fulfillRandomWords. + */ + function requestRandomWords( + bytes32 keyHash, + uint64 subId, + uint16 minimumRequestConfirmations, + uint32 callbackGasLimit, + uint32 numWords + ) external returns (uint256 requestId); + + /** + * @notice Create a VRF subscription. + * @return subId - A unique subscription id. + * @dev You can manage the consumer set dynamically with addConsumer/removeConsumer. + * @dev Note to fund the subscription, use transferAndCall. For example + * @dev LINKTOKEN.transferAndCall( + * @dev address(COORDINATOR), + * @dev amount, + * @dev abi.encode(subId)); + */ + function createSubscription() external returns (uint64 subId); + + /** + * @notice Get a VRF subscription. + * @param subId - ID of the subscription + * @return balance - LINK balance of the subscription in juels. + * @return reqCount - number of requests for this subscription, determines fee tier. + * @return owner - owner of the subscription. + * @return consumers - list of consumer address which are able to use this subscription. + */ + function getSubscription( + uint64 subId + ) external view returns (uint96 balance, uint64 reqCount, address owner, address[] memory consumers); + + /** + * @notice Request subscription owner transfer. + * @param subId - ID of the subscription + * @param newOwner - proposed new owner of the subscription + */ + function requestSubscriptionOwnerTransfer(uint64 subId, address newOwner) external; + + /** + * @notice Request subscription owner transfer. + * @param subId - ID of the subscription + * @dev will revert if original owner of subId has + * not requested that msg.sender become the new owner. + */ + function acceptSubscriptionOwnerTransfer(uint64 subId) external; + + /** + * @notice Add a consumer to a VRF subscription. + * @param subId - ID of the subscription + * @param consumer - New consumer which can use the subscription + */ + function addConsumer(uint64 subId, address consumer) external; + + /** + * @notice Remove a consumer from a VRF subscription. + * @param subId - ID of the subscription + * @param consumer - Consumer to remove from the subscription + */ + function removeConsumer(uint64 subId, address consumer) external; + + /** + * @notice Cancel a subscription + * @param subId - ID of the subscription + * @param to - Where to send the remaining LINK to + */ + function cancelSubscription(uint64 subId, address to) external; + + /* + * @notice Check to see if there exists a request commitment consumers + * for all consumers and keyhashes for a given sub. + * @param subId - ID of the subscription + * @return true if there exists at least one unfulfilled request for the subscription, false + * otherwise. + */ + function pendingRequestExists(uint64 subId) external view returns (bool); +} \ No newline at end of file diff --git a/contracts/Aavegotchi/libraries/LibAppStorage.sol b/contracts/Aavegotchi/libraries/LibAppStorage.sol index c0928bd5a..acd38c8ce 100644 --- a/contracts/Aavegotchi/libraries/LibAppStorage.sol +++ b/contracts/Aavegotchi/libraries/LibAppStorage.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.1; import {LibDiamond} from "../../shared/libraries/LibDiamond.sol"; import {LibMeta} from "../../shared/libraries/LibMeta.sol"; -import {ILink} from "../interfaces/ILink.sol"; + import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; import {IERC7589} from "../../shared/interfaces/IERC7589.sol"; @@ -11,6 +11,10 @@ uint256 constant NUMERIC_TRAITS_NUM = 6; uint256 constant TRAIT_BONUSES_NUM = 5; uint256 constant PORTAL_AAVEGOTCHIS_NUM = 10; +uint16 constant REQUEST_CONFIRMATIONS = 3; +uint32 constant NO_OF_WORDS = 1; +uint32 constant VRF_GAS_LIMIT = 2_500_000; + // switch (traitType) { // case 0: // return energy(value); @@ -289,12 +293,11 @@ struct AppStorage { string itemsBaseUri; bytes32 domainSeparator; //VRF - mapping(bytes32 => uint256) vrfRequestIdToTokenId; - mapping(bytes32 => uint256) vrfNonces; + mapping(uint256 => uint256) vrfRequestIdToTokenId; + // mapping(bytes32 => uint256) vrfNonces; bytes32 keyHash; - uint144 fee; + uint64 subscriptionId; address vrfCoordinator; - ILink link; // Marketplace uint256 nextERC1155ListingId; // erc1155 category => erc1155Order @@ -383,6 +386,8 @@ struct AppStorage { // states for erc1155 buy orders uint256 nextERC1155BuyOrderId; mapping(uint256 => ERC1155BuyOrder) erc1155BuyOrders; // buyOrderId => data + address gotchGeistBridge; + address itemGeistBridge; } library LibAppStorage { @@ -449,6 +454,18 @@ contract Modifiers { _; } + modifier onlyGotchiGeistBridge() { + address sender = LibMeta.msgSender(); + require(sender == s.gotchGeistBridge, "LibAppStorage: Do not have access"); + _; + } + + modifier onlyItemGeistBridge() { + address sender = LibMeta.msgSender(); + require(sender == s.itemGeistBridge, "LibAppStorage: Do not have access"); + _; + } + modifier onlyPeriphery() { address sender = LibMeta.msgSender(); require(sender == s.wearableDiamond, "LibAppStorage: Not wearable diamond"); diff --git a/contracts/shared/interfaces/INFTBridge.sol b/contracts/shared/interfaces/INFTBridge.sol new file mode 100644 index 000000000..00411ed6c --- /dev/null +++ b/contracts/shared/interfaces/INFTBridge.sol @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.1; + +interface INFTBridge { + function bridge( + address receiver_, + address tokenOwner_, + uint256 tokenId_, + uint256 amount_, + uint256 msgGasLimit_, + address connector_, + bytes calldata extraData_, + bytes calldata options_ + ) external payable; + + function receiveInbound( + uint32 siblingChainSlug_, + bytes memory payload_ + ) external payable; + + function retry(address connector_, bytes32 messageId_) external; +} diff --git a/hardhat.config.ts b/hardhat.config.ts index 3ba8ff5ea..9c7a2e525 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -38,7 +38,9 @@ require("./tasks/deployXPDrop"); // Go to https://buidler.dev/config/ to learn more export default { etherscan: { - apiKey: process.env.POLYGON_API_KEY, + apiKey: { + matic: process.env.POLYGON_API_KEY, + }, }, networks: { hardhat: { @@ -72,7 +74,14 @@ export default { gasPrice: 1000000000, timeout: 90000, }, - + amoy: { + url: process.env.AMOY_URL, + accounts: [process.env.SECRET], + }, + "base-sepolia": { + url: process.env.BASE_SEPOLIA_URL, + accounts: [process.env.SECRET], + }, // gorli: { // url: process.env.GORLI, // accounts: [process.env.SECRET], diff --git a/helpers/constants.ts b/helpers/constants.ts index 8fabe3599..c3a14a171 100644 --- a/helpers/constants.ts +++ b/helpers/constants.ts @@ -66,6 +66,13 @@ export const CORE_PET_LEGENDARY = WEARABLE_GAP_OFFSET + 41; export const CORE_PET_MYTHICAL = WEARABLE_GAP_OFFSET + 42; export const CORE_PET_GODLIKE = WEARABLE_GAP_OFFSET + 43; +export const AMOY_DIAMOND = "0xC80DB01aeDAD5F6E3088c75F60E52f579Cf1D3Cb"; +export const AMOY_DIAMOND_OWNER = "0xB9D736c48351Bad464710ee73BA80A0A659c1795"; +export const AMOY_GHST = "0xF679b8D109b2d23931237Ce948a7D784727c0897"; +export const AMOY_WEARABLE_DIAMOND = + "0xAA201d960404140296Ea85570940830be08DAc70"; +export const AMOY_FORGE_DIAMOND = "0xF7c2AC46723Ad844620F798ECe67f5C673120FB6"; + export enum ERC1155_BAAZAAR_CATEGORY_TO_ID { WEARABLE = 0, BADGE = 1, @@ -84,7 +91,6 @@ export enum ERC721_BAAZAAR_CATEGORY_TO_ID { REALM = 4, FAKEGOTCHIS = 5, } - export enum WEARABLE_BASE_QUANTITIES { COMMON = 1000, UNCOMMON = 500, diff --git a/js/diamond-util/src/index.js b/js/diamond-util/src/index.js index 4bc2ba900..14eb4f0d4 100644 --- a/js/diamond-util/src/index.js +++ b/js/diamond-util/src/index.js @@ -1,101 +1,113 @@ /* global ethers */ +const { ethers } = require("hardhat"); + const FacetCutAction = { Add: 0, Replace: 1, - Remove: 2 -} + Remove: 2, +}; // eslint-disable-next-line no-unused-vars -function getSignatures (contract) { - return Object.keys(contract.interface.functions) +function getSignatures(contract) { + return Object.keys(contract.interface.functions); } -function getSelectors (contract) { - const signatures = Object.keys(contract.interface.functions) +function getSelectors(contract) { + const signatures = Object.keys(contract.interface.functions); const selectors = signatures.reduce((acc, val) => { - if (val !== 'init(bytes)') { - acc.push(contract.interface.getSighash(val)) + if (val !== "init(bytes)") { + acc.push(contract.interface.getSighash(val)); } - return acc - }, []) - return selectors + return acc; + }, []); + return selectors; } -async function deployFacets (facets) { - console.log('--') - const deployed = [] +async function deployFacets(facets) { + console.log("--"); + const deployed = []; for (const facet of facets) { if (Array.isArray(facet)) { - if (typeof facet[0] !== 'string') { - throw Error(`Error using facet: facet name must be a string. Bad input: ${facet[0]}`) + if (typeof facet[0] !== "string") { + throw Error( + `Error using facet: facet name must be a string. Bad input: ${facet[0]}` + ); } if (!(facet[1] instanceof ethers.Contract)) { - throw Error(`Error using facet: facet must be a Contract. Bad input: ${facet[1]}`) + throw Error( + `Error using facet: facet must be a Contract. Bad input: ${facet[1]}` + ); } - console.log(`Using already deployed ${facet[0]}: ${facet[1].address}`) - console.log('--') - deployed.push(facet) + console.log(`Using already deployed ${facet[0]}: ${facet[1].address}`); + console.log("--"); + deployed.push(facet); } else { - if (typeof facet !== 'string') { - throw Error(`Error deploying facet: facet name must be a string. Bad input: ${facet}`) + if (typeof facet !== "string") { + throw Error( + `Error deploying facet: facet name must be a string. Bad input: ${facet}` + ); } - const facetFactory = await ethers.getContractFactory(facet) - console.log(`Deploying ${facet}`) - const deployedFactory = await facetFactory.deploy() - await deployedFactory.deployed() - console.log(`${facet} deployed: ${deployedFactory.address}`) - console.log('--') - deployed.push([facet, deployedFactory]) + const facetFactory = await ethers.getContractFactory(facet); + console.log(`Deploying ${facet}`); + const deployedFactory = await facetFactory.deploy(); + await deployedFactory.deployed(); + console.log(`${facet} deployed: ${deployedFactory.address}`); + console.log("--"); + deployed.push([facet, deployedFactory]); } } - return deployed + return deployed; } -async function deploy ({ +async function deploy({ diamondName, initDiamond, facets, owner, args = [], - txArgs = {} + txArgs = {}, }) { if (arguments.length !== 1) { - throw Error(`Requires only 1 map argument. ${arguments.length} arguments used.`) + throw Error( + `Requires only 1 map argument. ${arguments.length} arguments used.` + ); } - facets = await deployFacets(facets) - const diamondFactory = await ethers.getContractFactory('Diamond') - const diamondCut = [] - console.log('--') - console.log('Setting up diamondCut args') - console.log('--') + facets = await deployFacets(facets); + const diamondFactory = await ethers.getContractFactory("Diamond"); + const diamondCut = []; + console.log("--"); + console.log("Setting up diamondCut args"); + console.log("--"); for (const [name, deployedFacet] of facets) { - console.log(name) - console.log(getSignatures(deployedFacet)) - console.log('--') + console.log(name); + console.log(getSignatures(deployedFacet)); + console.log("--"); diamondCut.push([ deployedFacet.address, FacetCutAction.Add, - getSelectors(deployedFacet) - ]) + getSelectors(deployedFacet), + ]); } - console.log('--') - - let result - if (typeof initDiamond === 'string') { - const initDiamondName = initDiamond - console.log(`Deploying ${initDiamondName}`) - initDiamond = await ethers.getContractFactory(initDiamond) - initDiamond = await initDiamond.deploy() - await initDiamond.deployed() - result = await initDiamond.deployTransaction.wait() + console.log("--"); + + let result; + if (typeof initDiamond === "string") { + const initDiamondName = initDiamond; + console.log(`Deploying ${initDiamondName}`); + initDiamond = await ethers.getContractFactory(initDiamond); + initDiamond = await initDiamond.deploy(); + await initDiamond.deployed(); + result = await initDiamond.deployTransaction.wait(); if (!result.status) { - throw (Error(`Deploying ${initDiamondName} TRANSACTION FAILED!!! -------------------------------------------`)) + throw Error( + `Deploying ${initDiamondName} TRANSACTION FAILED!!! -------------------------------------------` + ); } } - console.log('Encoding diamondCut init function call') - const functionCall = initDiamond.interface.encodeFunctionData('init', args) + console.log("Encoding diamondCut init function call"); + const functionCall = initDiamond.interface.encodeFunctionData("init", args); // let functionCall // if (args.length > 0) { // functionCall = initDiamond.interface.encodeFunctionData("init", ...args) @@ -103,194 +115,321 @@ async function deploy ({ // functionCall = initDiamond.interface.encodeFunctionData() // } - console.log(`Deploying ${diamondName}`) + console.log(`Deploying ${diamondName}`); - const deployedDiamond = await diamondFactory.deploy(owner) - await deployedDiamond.deployed() - result = await deployedDiamond.deployTransaction.wait() + const deployedDiamond = await diamondFactory.deploy(owner); + await deployedDiamond.deployed(); + result = await deployedDiamond.deployTransaction.wait(); if (!result.status) { - console.log('Deploying diamond TRANSACTION FAILED!!! -------------------------------------------') - console.log('See block explorer app for details.') - console.log('Transaction hash:' + deployedDiamond.deployTransaction.hash) - throw (Error('failed to deploy diamond')) + console.log( + "Deploying diamond TRANSACTION FAILED!!! -------------------------------------------" + ); + console.log("See block explorer app for details."); + console.log("Transaction hash:" + deployedDiamond.deployTransaction.hash); + throw Error("failed to deploy diamond"); } - console.log('Diamond deploy transaction hash:' + deployedDiamond.deployTransaction.hash) + console.log( + "Diamond deploy transaction hash:" + deployedDiamond.deployTransaction.hash + ); - console.log(`${diamondName} deployed: ${deployedDiamond.address}`) - console.log(`Diamond owner: ${owner}`) + console.log(`${diamondName} deployed: ${deployedDiamond.address}`); + console.log(`Diamond owner: ${owner}`); - const diamondCutFacet = await ethers.getContractAt('DiamondCutFacet', deployedDiamond.address) - const tx = await diamondCutFacet.diamondCut(diamondCut, initDiamond.address, functionCall, txArgs) + const diamondCutFacet = await ethers.getContractAt( + "DiamondCutFacet", + deployedDiamond.address + ); + const tx = await diamondCutFacet.diamondCut( + diamondCut, + initDiamond.address, + functionCall, + txArgs + ); // console.log(`${diamondName} diamondCut arguments:`) // console.log(JSON.stringify([facets, initDiamond.address, args], null, 4)) - result = await tx.wait() + result = await tx.wait(); + if (!result.status) { + console.log( + "TRANSACTION FAILED!!! -------------------------------------------" + ); + console.log("See block explorer app for details."); + } + console.log("DiamondCut success!"); + console.log("Transaction hash:" + tx.hash); + console.log("--"); + return deployedDiamond; +} + +async function deployWithoutInit({ + diamondName, + facets, + args = [], + txArgs = {}, +}) { + if (arguments.length !== 1) { + throw Error( + `Requires only 1 map argument. ${arguments.length} arguments used.` + ); + } + facets = await deployFacets(facets); + const diamondFactory = await ethers.getContractFactory(diamondName); + const diamondCut = []; + console.log("--"); + console.log("Setting up diamondCut args"); + console.log("--"); + for (const [name, deployedFacet] of facets) { + console.log(name); + console.log(getSignatures(deployedFacet)); + console.log("--"); + diamondCut.push([ + deployedFacet.address, + FacetCutAction.Add, + getSelectors(deployedFacet), + ]); + } + console.log("--"); + + let result; + + console.log(`Deploying ${diamondName}`); + console.log(...args); + const deployedDiamond = await diamondFactory.deploy(...args); + console.log("here1"); + await deployedDiamond.deployed(); + console.log("here2"); + result = await deployedDiamond.deployTransaction.wait(); + if (!result.status) { + console.log( + "Deploying diamond TRANSACTION FAILED!!! -------------------------------------------" + ); + console.log("See block explorer app for details."); + console.log("Transaction hash:" + deployedDiamond.deployTransaction.hash); + throw Error("failed to deploy diamond"); + } + console.log( + "Diamond deploy transaction hash:" + deployedDiamond.deployTransaction.hash + ); + + console.log(`${diamondName} deployed: ${deployedDiamond.address}`); + + const diamondCutFacet = await ethers.getContractAt( + "DiamondCutFacet", + deployedDiamond.address + ); + const tx = await diamondCutFacet.diamondCut( + diamondCut, + ethers.constants.AddressZero, + "0x", + txArgs + ); + + result = await tx.wait(); if (!result.status) { - console.log('TRANSACTION FAILED!!! -------------------------------------------') - console.log('See block explorer app for details.') + console.log( + "TRANSACTION FAILED!!! -------------------------------------------" + ); + console.log("See block explorer app for details."); } - console.log('DiamondCut success!') - console.log('Transaction hash:' + tx.hash) - console.log('--') - return deployedDiamond + console.log("DiamondCut success!"); + console.log("Transaction hash:" + tx.hash); + console.log("--"); + return deployedDiamond; } -function inFacets (selector, facets) { +function inFacets(selector, facets) { for (const facet of facets) { if (facet.functionSelectors.includes(selector)) { - return true + return true; } } - return false + return false; } -async function upgrade ({ +async function upgrade({ diamondAddress, diamondCut, txArgs = {}, initFacetName = undefined, - initArgs + initArgs, }) { if (arguments.length !== 1) { - throw Error(`Requires only 1 map argument. ${arguments.length} arguments used.`) + throw Error( + `Requires only 1 map argument. ${arguments.length} arguments used.` + ); } - const diamondCutFacet = await ethers.getContractAt('DiamondCutFacet', diamondAddress) - const diamondLoupeFacet = await ethers.getContractAt('DiamondLoupeFacet', diamondAddress) - const existingFacets = await diamondLoupeFacet.facets() - const facetFactories = new Map() + const diamondCutFacet = await ethers.getContractAt( + "DiamondCutFacet", + diamondAddress + ); + const diamondLoupeFacet = await ethers.getContractAt( + "DiamondLoupeFacet", + diamondAddress + ); + const existingFacets = await diamondLoupeFacet.facets(); + const facetFactories = new Map(); - console.log('Facet Signatures and Selectors: ') + console.log("Facet Signatures and Selectors: "); for (const facet of diamondCut) { - const functions = new Map() - const selectors = [] - console.log('Facet: ' + facet) - let facetName - let contract + const functions = new Map(); + const selectors = []; + console.log("Facet: " + facet); + let facetName; + let contract; if (Array.isArray(facet[0])) { - facetName = facet[0][0] - contract = facet[0][1] - if (!(typeof facetName === 'string')) { - throw Error('First value in facet[0] array must be a string.') + facetName = facet[0][0]; + contract = facet[0][1]; + if (!(typeof facetName === "string")) { + throw Error("First value in facet[0] array must be a string."); } if (!(contract instanceof ethers.Contract)) { - throw Error('Second value in facet[0] array must be a Contract object.') + throw Error( + "Second value in facet[0] array must be a Contract object." + ); } - facet[0] = facetName + facet[0] = facetName; } else { - facetName = facet[0] - if (!(typeof facetName === 'string') && facetName) { - throw Error('facet[0] must be a string or an array or false.') + facetName = facet[0]; + if (!(typeof facetName === "string") && facetName) { + throw Error("facet[0] must be a string or an array or false."); } } for (const signature of facet[2]) { - const selector = ethers.utils.keccak256(ethers.utils.toUtf8Bytes(signature)).slice(0, 10) - console.log(`Function: ${selector} ${signature}`) - selectors.push(selector) - functions.set(selector, signature) + const selector = ethers.utils + .keccak256(ethers.utils.toUtf8Bytes(signature)) + .slice(0, 10); + console.log(`Function: ${selector} ${signature}`); + selectors.push(selector); + functions.set(selector, signature); } - console.log('') + console.log(""); if (facet[1] === FacetCutAction.Remove) { if (facetName) { - throw (Error(`Can't remove functions because facet name must have a false value not ${facetName}.`)) + throw Error( + `Can't remove functions because facet name must have a false value not ${facetName}.` + ); } - facet[0] = ethers.constants.AddressZero + facet[0] = ethers.constants.AddressZero; for (const selector of selectors) { if (!inFacets(selector, existingFacets)) { - const signature = functions.get(selector) - throw Error(`Can't remove '${signature}'. It doesn't exist in deployed diamond.`) + const signature = functions.get(selector); + throw Error( + `Can't remove '${signature}'. It doesn't exist in deployed diamond.` + ); } } - facet[2] = selectors + facet[2] = selectors; } else if (facet[1] === FacetCutAction.Replace) { - let facetFactory = facetFactories.get(facetName) + let facetFactory = facetFactories.get(facetName); if (!facetFactory) { if (contract) { - facetFactories.set(facetName, contract) + facetFactories.set(facetName, contract); } else { - facetFactory = await ethers.getContractFactory(facetName) - facetFactories.set(facetName, facetFactory) + facetFactory = await ethers.getContractFactory(facetName); + facetFactories.set(facetName, facetFactory); } } for (const signature of facet[2]) { - if (!Object.prototype.hasOwnProperty.call(facetFactory.interface.functions, signature)) { - throw (Error(`Can't replace '${signature}'. It doesn't exist in ${facetName} source code.`)) + if ( + !Object.prototype.hasOwnProperty.call( + facetFactory.interface.functions, + signature + ) + ) { + throw Error( + `Can't replace '${signature}'. It doesn't exist in ${facetName} source code.` + ); } } for (const selector of selectors) { if (!inFacets(selector, existingFacets)) { - const signature = functions.get(selector) - throw Error(`Can't replace '${signature}'. It doesn't exist in deployed diamond.`) + const signature = functions.get(selector); + throw Error( + `Can't replace '${signature}'. It doesn't exist in deployed diamond.` + ); } } - facet[2] = selectors + facet[2] = selectors; } else if (facet[1] === FacetCutAction.Add) { - let facetFactory = facetFactories.get(facetName) + let facetFactory = facetFactories.get(facetName); if (!facetFactory) { if (contract) { - facetFactories.set(facetName, contract) + facetFactories.set(facetName, contract); } else { - facetFactory = await ethers.getContractFactory(facetName) - facetFactories.set(facetName, facetFactory) + facetFactory = await ethers.getContractFactory(facetName); + facetFactories.set(facetName, facetFactory); } } for (const signature of facet[2]) { - if (!Object.prototype.hasOwnProperty.call(facetFactory.interface.functions, signature)) { - throw (Error(`Can't add ${signature}. It doesn't exist in ${facetName} source code.`)) + if ( + !Object.prototype.hasOwnProperty.call( + facetFactory.interface.functions, + signature + ) + ) { + throw Error( + `Can't add ${signature}. It doesn't exist in ${facetName} source code.` + ); } } for (const selector of selectors) { if (inFacets(selector, existingFacets)) { - const signature = functions.get(selector) - throw Error(`Can't add '${signature}'. It already exists in deployed diamond.`) + const signature = functions.get(selector); + throw Error( + `Can't add '${signature}'. It already exists in deployed diamond.` + ); } } - facet[2] = selectors + facet[2] = selectors; } else { - throw (Error('Incorrect FacetCutAction value. Must be 0, 1 or 2. Value used: ' + facet[1])) + throw Error( + "Incorrect FacetCutAction value. Must be 0, 1 or 2. Value used: " + + facet[1] + ); } } // deploying new facets - const alreadDeployed = new Map() + const alreadDeployed = new Map(); for (const facet of diamondCut) { if (facet[1] !== FacetCutAction.Remove) { - const existingAddress = alreadDeployed.get(facet[0]) + const existingAddress = alreadDeployed.get(facet[0]); if (existingAddress) { - facet[0] = existingAddress - continue + facet[0] = existingAddress; + continue; } - console.log(`Deploying ${facet[0]}`) - const facetFactory = facetFactories.get(facet[0]) - let deployedFacet = facetFactory + console.log(`Deploying ${facet[0]}`); + const facetFactory = facetFactories.get(facet[0]); + let deployedFacet = facetFactory; if (!(deployedFacet instanceof ethers.Contract)) { - deployedFacet = await facetFactory.deploy() - await deployedFacet.deployed() + deployedFacet = await facetFactory.deploy(); + await deployedFacet.deployed(); } - facetFactories.set(facet[0], deployedFacet) - console.log(`${facet[0]} deployed: ${deployedFacet.address}`) - alreadDeployed.set(facet[0], deployedFacet.address) - facet[0] = deployedFacet.address + facetFactories.set(facet[0], deployedFacet); + console.log(`${facet[0]} deployed: ${deployedFacet.address}`); + alreadDeployed.set(facet[0], deployedFacet.address); + facet[0] = deployedFacet.address; } } - console.log('diamondCut arg:') - console.log(diamondCut) + console.log("diamondCut arg:"); + console.log(diamondCut); - let initFacetAddress = ethers.constants.AddressZero - let functionCall = '0x' + let initFacetAddress = ethers.constants.AddressZero; + let functionCall = "0x"; if (initFacetName !== undefined) { - let initFacet = facetFactories.get(initFacetName) + let initFacet = facetFactories.get(initFacetName); if (!initFacet) { - const InitFacet = await ethers.getContractFactory(initFacetName) - initFacet = await InitFacet.deploy() - await initFacet.deployed() - console.log('Deployed init facet: ' + initFacet.address) + const InitFacet = await ethers.getContractFactory(initFacetName); + initFacet = await InitFacet.deploy(); + await initFacet.deployed(); + console.log("Deployed init facet: " + initFacet.address); } else { - console.log('Using init facet: ' + initFacet.address) + console.log("Using init facet: " + initFacet.address); } - functionCall = initFacet.interface.encodeFunctionData('init', initArgs) - console.log('Function call: ') - console.log(functionCall) - initFacetAddress = initFacet.address + functionCall = initFacet.interface.encodeFunctionData("init", initArgs); + console.log("Function call: "); + console.log(functionCall); + initFacetAddress = initFacet.address; } const result = await diamondCutFacet.diamondCut( @@ -298,126 +437,137 @@ async function upgrade ({ initFacetAddress, functionCall, txArgs - ) - const receipt = await result.wait() + ); + const receipt = await result.wait(); if (!receipt.status) { - console.log('TRANSACTION FAILED!!! -------------------------------------------') - console.log('See block explorer app for details.') + console.log( + "TRANSACTION FAILED!!! -------------------------------------------" + ); + console.log("See block explorer app for details."); } - console.log('------') - console.log('Upgrade transaction hash: ' + result.hash) - return result + console.log("------"); + console.log("Upgrade transaction hash: " + result.hash); + return result; } -async function upgradeWithNewFacets ({ +async function upgradeWithNewFacets({ diamondAddress, facetNames, selectorsToRemove = [], initFacetName = undefined, - initArgs = [] + initArgs = [], }) { if (arguments.length === 1) { - throw Error(`Requires only 1 map argument. ${arguments.length} arguments used.`) + throw Error( + `Requires only 1 map argument. ${arguments.length} arguments used.` + ); } - const diamondCutFacet = await ethers.getContractAt('DiamondCutFacet', diamondAddress) - const diamondLoupeFacet = await ethers.getContractAt('DiamondLoupeFacet', diamondAddress) + const diamondCutFacet = await ethers.getContractAt( + "DiamondCutFacet", + diamondAddress + ); + const diamondLoupeFacet = await ethers.getContractAt( + "DiamondLoupeFacet", + diamondAddress + ); - const diamondCut = [] - const existingFacets = await diamondLoupeFacet.facets() - const undeployed = [] - const deployed = [] + const diamondCut = []; + const existingFacets = await diamondLoupeFacet.facets(); + const undeployed = []; + const deployed = []; for (const name of facetNames) { - console.log(name) - const facetFactory = await ethers.getContractFactory(name) - undeployed.push([name, facetFactory]) + console.log(name); + const facetFactory = await ethers.getContractFactory(name); + undeployed.push([name, facetFactory]); } if (selectorsToRemove.length > 0) { // check if any selectorsToRemove are already gone for (const selector of selectorsToRemove) { if (!inFacets(selector, existingFacets)) { - throw Error('Function selector to remove is already gone.') + throw Error("Function selector to remove is already gone."); } } diamondCut.push([ ethers.constants.AddressZeo, FacetCutAction.Remove, - selectorsToRemove - ]) + selectorsToRemove, + ]); } for (const [name, facetFactory] of undeployed) { - console.log(`Deploying ${name}`) - deployed.push([name, await facetFactory.deploy()]) + console.log(`Deploying ${name}`); + deployed.push([name, await facetFactory.deploy()]); } for (const [name, deployedFactory] of deployed) { - await deployedFactory.deployed() - console.log('--') - console.log(`${name} deployed: ${deployedFactory.address}`) - const add = [] - const replace = [] + await deployedFactory.deployed(); + console.log("--"); + console.log(`${name} deployed: ${deployedFactory.address}`); + const add = []; + const replace = []; for (const selector of getSelectors(deployedFactory)) { if (!inFacets(selector, existingFacets)) { - add.push(selector) + add.push(selector); } else { - replace.push(selector) + replace.push(selector); } } if (add.length > 0) { - diamondCut.push([deployedFactory.address, FacetCutAction.Add, add]) + diamondCut.push([deployedFactory.address, FacetCutAction.Add, add]); } if (replace.length > 0) { diamondCut.push([ deployedFactory.address, FacetCutAction.Replace, - replace - ]) + replace, + ]); } } - console.log('diamondCut arg:') - console.log(diamondCut) - console.log('------') + console.log("diamondCut arg:"); + console.log(diamondCut); + console.log("------"); - let initFacetAddress = ethers.constants.AddressZero - let functionCall = '0x' + let initFacetAddress = ethers.constants.AddressZero; + let functionCall = "0x"; if (initFacetName !== undefined) { - let initFacet + let initFacet; for (const [name, deployedFactory] of deployed) { if (name === initFacetName) { - initFacet = deployedFactory - break + initFacet = deployedFactory; + break; } } if (!initFacet) { - const InitFacet = await ethers.getContractFactory(initFacetName) - initFacet = await InitFacet.deploy() - await initFacet.deployed() - console.log('Deployed init facet: ' + initFacet.address) + const InitFacet = await ethers.getContractFactory(initFacetName); + initFacet = await InitFacet.deploy(); + await initFacet.deployed(); + console.log("Deployed init facet: " + initFacet.address); } else { - console.log('Using init facet: ' + initFacet.address) + console.log("Using init facet: " + initFacet.address); } - functionCall = initFacet.interface.encodeFunctionData('init', initArgs) - console.log('Function call: ') - console.log(functionCall) - initFacetAddress = initFacet.address + functionCall = initFacet.interface.encodeFunctionData("init", initArgs); + console.log("Function call: "); + console.log(functionCall); + initFacetAddress = initFacet.address; } const result = await diamondCutFacet.diamondCut( diamondCut, initFacetAddress, functionCall - ) - console.log('------') - console.log('Upgrade transaction hash: ' + result.hash) - return result + ); + console.log("------"); + console.log("Upgrade transaction hash: " + result.hash); + return result; } -exports.FacetCutAction = FacetCutAction -exports.upgrade = upgrade -exports.upgradeWithNewFacets = upgradeWithNewFacets -exports.getSelectors = getSelectors -exports.deployFacets = deployFacets -exports.deploy = deploy -exports.inFacets = inFacets -exports.upgrade = upgrade +exports.FacetCutAction = FacetCutAction; +exports.upgrade = upgrade; +exports.upgradeWithNewFacets = upgradeWithNewFacets; +exports.getSelectors = getSelectors; +exports.deployFacets = deployFacets; +exports.deploy = deploy; +exports.deployWithoutInit = deployWithoutInit; +exports.inFacets = inFacets; +exports.upgrade = upgrade; diff --git a/scripts/batchMintPortals.js b/scripts/batchMintPortals.js index 05bf70723..27e5fb3a4 100644 --- a/scripts/batchMintPortals.js +++ b/scripts/batchMintPortals.js @@ -7,7 +7,8 @@ async function batchMintPortals() { console.log("account:", account); let nonceManagedSigner; - const itemManager = "0x8D46fd7160940d89dA026D59B2e819208E714E82"; + const itemManager = "0xd38Df837a1EAd12ee16f8b8b7E5F58703f841668"; + let diamondAddress = "0x87C969d083189927049f8fF3747703FB9f7a8AEd"; const gasPrice = 50000000000; @@ -20,7 +21,7 @@ async function batchMintPortals() { }); signer = await ethers.provider.getSigner(itemManager); nonceManagedSigner = new NonceManager(signer); - } else if (hre.network.name === "matic") { + } else if (hre.network.name === "base-sepolia") { signer = accounts[0]; // new ethers.Wallet(process.env.ITEM_MANAGER); } else { throw Error("Incorrect network selected"); @@ -29,25 +30,37 @@ async function batchMintPortals() { console.log("Deploying Account: " + itemManager + "\n---"); let totalGasUsed = ethers.BigNumber.from("0"); - let shopFacet; - let diamondAddress = "0x86935F11C86623deC8a25696E1C19a8659CbF95d"; console.log(`Batch minting Portals to Item Manager: ${itemManager}`); - shopFacet = await ethers.getContractAt( + const shopFacet = await ethers.getContractAt( "ShopFacet", diamondAddress, nonceManagedSigner ); - - let numberPerMint = 50; - const maxNumber = 50; //15000; - //Mint 2000 ERC721s - + const vrfFacet = await ethers.getContractAt( + "VrfFacet", + diamondAddress, + nonceManagedSigner + ); const gameFacet = await ethers.getContractAt( + "AavegotchiGameFacet", + diamondAddress, + nonceManagedSigner + ); + const aavegotchiFacet = await ethers.getContractAt( "contracts/Aavegotchi/facets/AavegotchiFacet.sol:AavegotchiFacet", diamondAddress ); + const ghstFacet = await ethers.getContractAt( + "GHSTFacet", + "0xe97f36a00058aa7dfc4e85d23532c3f70453a7ae" + ); + await ghstFacet.approve(diamondAddress, ethers.utils.parseEther("100000000000000000000000")); + + let numberPerMint = 50; + const maxNumber = 500; //15000; + //Mint 2000 ERC721s let remaining = maxNumber; @@ -68,12 +81,32 @@ async function batchMintPortals() { totalGasUsed = totalGasUsed.add(r.gasLimit); promises.push(r); console.log("Total minted:", totalMinted); - const balance = await gameFacet.balanceOf(itemManager); + const balance = await aavegotchiFacet.balanceOf(itemManager); console.log("Balance of Item Manager:", balance.toString()); } await Promise.all(promises); + // open portals + const startId = 50 + for (let i = 0; i < 5; i++) { + let r = await vrfFacet.openPortals(Array.from({ length: 20 }, (_, j) => j + startId + i * 20), { + gasPrice: gasPrice, + }); + console.log(`open portal from ${startId + i * 20}: tx hash:`, r.hash); + } + + // claim gotchis + for (let i = 100; i < 150; i++) { + const gotchis = await gameFacet.portalAavegotchiTraits(i) + const selectedGotchi = gotchis[0] + let r = await gameFacet.claimAavegotchi(i, 0, selectedGotchi.minimumStake, { + gasPrice: gasPrice, + }); + console.log(`claimAavegotchi ${i}: tx hash:`, r.hash); + } + + console.log("Used Gas:", totalGasUsed.toString()); } diff --git a/scripts/deployFullDiamond.ts b/scripts/deployFullDiamond.ts new file mode 100644 index 000000000..590e9e481 --- /dev/null +++ b/scripts/deployFullDiamond.ts @@ -0,0 +1,742 @@ +/* global ethers hre */ + +import { ethers, network } from "hardhat"; + +import { + getItemTypes, + ItemTypeInputNew, + SleeveObject, + toItemTypeInputNew, +} from "./itemTypeHelpers"; +import { itemTypes as allItemTypes } from "../data/itemTypes/itemTypes"; +import { wearableSetArrays } from "./wearableSets"; + +import { DAOFacet, ERC1155BuyOrderFacet, SvgFacet } from "../typechain"; +import { BigNumberish, BigNumber } from "@ethersproject/bignumber"; +import { uploadSvgs } from "./svgHelperFunctions"; +import { getWearables } from "../svgs/allWearables"; +import { closedPortals, openedPortals } from "../svgs/portals"; + +import { setForgeProperties } from "./upgrades/forge/upgrade-forgeSetters"; +import { aavegotchiSvgs as aavegotchiSideSvgs } from "../svgs/aavegotchi-side-typeScript"; + +import { + eyeShapesLeftSvgs, + eyeShapesRightSvgs, +} from "../svgs/eyeShapes-sidesOpt"; +import { + wearablesLeftSvgs, + wearablesRightSvgs, + wearablesBackSvgs, + wearablesLeftSleeveSvgs, + wearablesRightSleeveSvgs, + wearablesBackSleeveSvgs, +} from "../svgs/wearables-sides"; + +import { aavegotchiSvgs } from "../svgs/aavegotchi-typescript"; +import { run } from "hardhat"; +import { allSideViewDimensions } from "../svgs/sideViewDimensions"; +import { convertSideDimensionsToTaskFormat } from "../tasks/updateItemSideDimensions"; +import { allExceptions } from "../svgs/allExceptions"; +import { convertExceptionsToTaskFormat } from "../tasks/updateWearableExceptions"; + +const diamond = require("../js/diamond-util/src/index.js"); +const { collaterals } = require("./testCollateralTypes.js"); + +function addCommas(nStr: any) { + nStr += ""; + const x = nStr.split("."); + let x1 = x[0]; + const x2 = x.length > 1 ? "." + x[1] : ""; + var rgx = /(\d+)(\d{3})/; + while (rgx.test(x1)) { + x1 = x1.replace(rgx, "$1" + "," + "$2"); + } + return x1 + x2; +} + +function strDisplay(str: any) { + return addCommas(str.toString()); +} + +async function main() { + if (!["hardhat", "localhost", "amoy", "base-sepolia"].includes(network.name)) { + throw Error("No network settings for " + network.name); + } + + //amoy + const ghstContract = "0xB40B75b4a8e5153357b3e5e4343d997B1a1019f9"; + const ghstStakingDiamondAddress = + "0xae83d5fc564Ef58224e934ba4Df72a100d5082a0"; + const realmDiamondAddress = "0x5a4faEb79951bAAa0866B72fD6517E693c8E4620"; + const installationDiamondAddress = + "0x514b7c55FB3DFf3533B58D85CD25Ba04bb30612D"; + const tileDiamondAddress = "0xCa6F4Ef19a1Beb9BeF12f64b395087E5680bcB22"; + const fakeGotchiArtDiamondAddress = + "0x330088c3372f4F78cF023DF16E1e1564109191dc"; //todo + const fakeGotchiCardDiamondAddress = + "0x9E282FE4a0be6A0C4B9f7d9fEF10547da35c52EA"; //todo + + const name = "Aavegotchi"; + const symbol = "GOTCHI"; + + const childChainManager = "0xb5505a6d998549090530911180f38aC5130101c6"; + const vrfCoordinatorAmoy = "0x7E10652Cb79Ba97bC1D0F38a1e8FaD8464a8a908"; // todo + const keyHash = + "0x3f631d5ec60a0ce16203bcd6aff7ffbc423e22e452786288e172d467354304c8"; // todo + const subscriptionIdAmoy = BigNumber.from(4534367); + + const fee = ethers.utils.parseEther("0.0001"); + + const accounts = await ethers.getSigners(); + const ownerAddress = await accounts[0].getAddress(); + + console.log("Owner: " + ownerAddress); + + const dao = ownerAddress; // 'todo' + const daoTreasury = ownerAddress; + const rarityFarming = ownerAddress; // 'todo' + const pixelCraft = ownerAddress; // 'todo' + const itemManagers = [ownerAddress]; // 'todo' + + const initArgs = [ + [ + dao, + daoTreasury, + pixelCraft, + rarityFarming, + ghstContract, + keyHash, + subscriptionIdAmoy, + vrfCoordinatorAmoy, + childChainManager, + name, + symbol, + ], + ]; + + const gasLimit = 12300000; + let totalGasUsed = ethers.BigNumber.from("0"); + let tx; + let receipt; + + async function deployFacets(...facets: any[]) { + const instances = []; + for (let facet of facets) { + let constructorArgs = []; + if (Array.isArray(facet)) { + [facet, constructorArgs] = facet; + } + const factory: any = await ethers.getContractFactory(facet); + const facetInstance = await factory.deploy(...constructorArgs); + await facetInstance.deployed(); + const tx = facetInstance.deployTransaction; + const receipt = await tx.wait(); + console.log(`${facet} deploy gas used:` + strDisplay(receipt.gasUsed)); + totalGasUsed = totalGasUsed.add(receipt.gasUsed); + instances.push(facetInstance); + } + return instances; + } + let [ + bridgeFacet, + aavegotchiFacet, + aavegotchiGameFacet, + svgFacet, + itemsFacet, + itemsTransferFacet, + collateralFacet, + daoFacet, + vrfFacet, + shopFacet, + metaTransactionsFacet, + erc1155MarketplaceFacet, + erc721MarketplaceFacet, + escrowFacet, + gotchiLendingFacet, + lendingGetterAndSetterFacet, + marketplaceGetterFacet, + svgViewsFacet, + wearableSetsFacet, + whitelistFacet, + peripheryFacet, + merkleDropFacet, + erc721BuyorderFacet, + itemsRolesRegistryFacet, + voucherMigrationFacet, + erc1155BuyOrderFacet, + polygonXGeistBridgeFacet, + ] = await deployFacets( + "contracts/Aavegotchi/facets/BridgeFacet.sol:BridgeFacet", + "contracts/Aavegotchi/facets/AavegotchiFacet.sol:AavegotchiFacet", + "AavegotchiGameFacet", + "SvgFacet", + "contracts/Aavegotchi/facets/ItemsFacet.sol:ItemsFacet", + "ItemsTransferFacet", + "CollateralFacet", + "DAOFacet", + "VrfFacet", + "ShopFacet", + "MetaTransactionsFacet", + "ERC1155MarketplaceFacet", + "ERC721MarketplaceFacet", + "EscrowFacet", + "GotchiLendingFacet", + "LendingGetterAndSetterFacet", + "MarketplaceGetterFacet", + "SvgViewsFacet", + "WearableSetsFacet", + "WhitelistFacet", + "PeripheryFacet", + "MerkleDropFacet", + "ERC721BuyOrderFacet", + "ItemsRolesRegistryFacet", + "VoucherMigrationFacet", + "ERC1155BuyOrderFacet", + "PolygonXGeistBridgeFacet" + ); + + const aavegotchiDiamond = await diamond.deploy({ + diamondName: "AavegotchiDiamond", + initDiamond: "contracts/Aavegotchi/InitDiamond.sol:InitDiamond", + facets: [ + ["BridgeFacet", bridgeFacet], + ["AavegotchiFacet", aavegotchiFacet], + ["AavegotchiGameFacet", aavegotchiGameFacet], + ["SvgFacet", svgFacet], + ["ItemsFacet", itemsFacet], + ["ItemsTransferFacet", itemsTransferFacet], + ["CollateralFacet", collateralFacet], + ["DAOFacet", daoFacet], + ["VrfFacet", vrfFacet], + ["ShopFacet", shopFacet], + ["MetaTransactionsFacet", metaTransactionsFacet], + ["ERC1155MarketplaceFacet", erc1155MarketplaceFacet], + ["ERC721MarketplaceFacet", erc721MarketplaceFacet], + ["EscrowFacet", escrowFacet], + ["GotchiLendingFacet", gotchiLendingFacet], + ["LendingGetterAndSetterFacet", lendingGetterAndSetterFacet], + ["MarketplaceGetterFacet", marketplaceGetterFacet], + ["SvgViewsFacet", svgViewsFacet], + ["WearableSetsFacet", wearableSetsFacet], + ["WhitelistFacet", whitelistFacet], + ["PeripheryFacet", peripheryFacet], + ["MerkleDropFacet", merkleDropFacet], + ["ERC721BuyOrderFacet", erc721BuyorderFacet], + ["ItemsRolesRegistryFacet", itemsRolesRegistryFacet], + ["VoucherMigrationFacet", voucherMigrationFacet], + ["ERC1155BuyOrderFacet", erc1155BuyOrderFacet], + ["PolygonXGeistBridgeFacet", polygonXGeistBridgeFacet], + ], + owner: ownerAddress, + args: initArgs, + }); + console.log("Aavegotchi diamond address:" + aavegotchiDiamond.address); + + tx = aavegotchiDiamond.deployTransaction; + receipt = await tx.wait(); + console.log( + "Aavegotchi diamond deploy gas used:" + strDisplay(receipt.gasUsed) + ); + totalGasUsed = totalGasUsed.add(receipt.gasUsed); + + const deets = await vrfFacet.getVrfInfo(); + console.log("Vrf info:", deets); + + // wearable diamond + + let [eventhandlerFacet, wearablesFacet] = await deployFacets( + "contracts/Aavegotchi/WearableDiamond/facets/EventHandlerFacet.sol:EventHandlerFacet", + "contracts/Aavegotchi/WearableDiamond/facets/WearablesFacet.sol:WearablesFacet" + ); + + //get constructor args from aavegotchi diamond + const [cutAddress, loupeAddress, ownershipAddress] = + await aavegotchiDiamond.getDefaultFacetAddresses(); + + const wearableDiamond = await diamond.deployWithoutInit({ + diamondName: "WearableDiamond", + facets: [ + ["EventHandlerFacet", eventhandlerFacet], + ["WearablesFacet", wearablesFacet], + ], + args: [ + ownerAddress, + cutAddress, + loupeAddress, + ownershipAddress, + aavegotchiDiamond.address, + ], + }); + + console.log("Wearable diamond address:" + wearableDiamond.address); + + tx = wearableDiamond.deployTransaction; + receipt = await tx.wait(); + console.log( + "Wearable diamond deploy gas used:" + strDisplay(receipt.gasUsed) + ); + + totalGasUsed = totalGasUsed.add(receipt.gasUsed); + + peripheryFacet = await ethers.getContractAt( + "PeripheryFacet", + aavegotchiDiamond.address + ); + + tx = await peripheryFacet.setPeriphery(wearableDiamond.address); + receipt = await tx.wait(); + if (!receipt.status) { + throw Error(`Error:: ${tx.hash}`); + } + console.log( + "Setting wearable diamond gas used::" + strDisplay(receipt.gasUsed) + ); + totalGasUsed = totalGasUsed.add(receipt.gasUsed); + + // forge diamond + let [forgeFacet, forgeDaoFacet, forgeTokenFacet, forgeVrfFacet] = + await deployFacets( + "contracts/Aavegotchi/ForgeDiamond/facets/ForgeFacet.sol:ForgeFacet", + "contracts/Aavegotchi/ForgeDiamond/facets/ForgeDAOFacet.sol:ForgeDAOFacet", + "contracts/Aavegotchi/ForgeDiamond/facets/ForgeTokenFacet.sol:ForgeTokenFacet", + "contracts/Aavegotchi/ForgeDiamond/facets/ForgeVRFFacet.sol:ForgeVRFFacet" + ); + + const forgeDiamond = await diamond.deployWithoutInit({ + diamondName: "ForgeDiamond", + facets: [ + ["ForgeFacet", forgeFacet], + ["ForgeDAOFacet", forgeDaoFacet], + ["ForgeTokenFacet", forgeTokenFacet], + ["ForgeVRFFacet", forgeVrfFacet], + ], + args: [ + ownerAddress, + cutAddress, + loupeAddress, + ownershipAddress, + aavegotchiDiamond.address, + wearableDiamond.address, + ], + }); + + console.log("Forge diamond address:" + forgeDiamond.address); + tx = wearableDiamond.deployTransaction; + receipt = await tx.wait(); + console.log( + "Wearable diamond deploy gas used:" + strDisplay(receipt.gasUsed) + ); + totalGasUsed = totalGasUsed.add(receipt.gasUsed); + + // get facets + daoFacet = await ethers.getContractAt("DAOFacet", aavegotchiDiamond.address); + aavegotchiGameFacet = await ethers.getContractAt( + "AavegotchiGameFacet", + aavegotchiDiamond.address + ); + erc1155MarketplaceFacet = await ethers.getContractAt( + "ERC1155MarketplaceFacet", + aavegotchiDiamond.address + ); + erc721MarketplaceFacet = await ethers.getContractAt( + "ERC721MarketplaceFacet", + aavegotchiDiamond.address + ); + + svgFacet = await ethers.getContractAt("SvgFacet", aavegotchiDiamond.address); + peripheryFacet = await ethers.getContractAt( + "PeripheryFacet", + aavegotchiDiamond.address + ); + + // add item managers + console.log("Adding item managers"); + tx = await daoFacet.addItemManagers(itemManagers, { gasLimit: gasLimit }); + console.log("Adding item managers tx:", tx.hash); + receipt = await tx.wait(); + if (!receipt.status) { + throw Error(`Adding item manager failed: ${tx.hash}`); + } + + // // create new haunt and upload payloads + let initialHauntSize = "10000"; + let portalPrice = ethers.utils.parseEther("0.1"); //0.1ghst/portal + tx = await daoFacet.createHaunt(initialHauntSize, portalPrice, "0x000000", { + gasLimit: gasLimit, + }); + receipt = await tx.wait(); + console.log("Haunt created:" + strDisplay(receipt.gasUsed)); + totalGasUsed = totalGasUsed.add(receipt.gasUsed); + + // add collateral info for haunt + console.log("Adding Collateral Types", collaterals); + + tx = await daoFacet.addCollateralTypes(1, collaterals, { + gasLimit: gasLimit, + }); + receipt = await tx.wait(); + console.log("Add Collateral Types gas used::" + strDisplay(receipt.gasUsed)); + totalGasUsed = totalGasUsed.add(receipt.gasUsed); + + // add item types + + //convert all itemtypes to itemTypeNew + let itemTypes2: ItemTypeInputNew[] = []; + for (let i = 0; i < allItemTypes.length; i++) { + itemTypes2.push(toItemTypeInputNew(allItemTypes[i])); + } + const itemTypes = getItemTypes(itemTypes2, ethers); + console.log("Adding", itemTypes2.length, "Item Types"); + let step = 20; + let totalItems = itemTypes.length; + let totalBatches = Math.ceil(totalItems / step); + + for (let i = 0; i < totalBatches; i++) { + const start = step * i; + const end = start + step; + const batch = itemTypes.slice(start, end); // Get current batch + + let tx = await daoFacet.addItemTypes(batch, { gasLimit: gasLimit }); + let receipt = await tx.wait(); + + // const itemIds = []; + // const quantities = []; + // batch.forEach((itemType) => { + // itemIds.push(itemType.svgId); + // quantities.push(itemType.maxQuantity); + // }); + // tx = await daoFacet.mintItems(ownerAddress, itemIds, quantities , { gasLimit: gasLimit }); + // receipt = await tx.wait(); + + if (!receipt.status) { + throw Error(`Error:: ${tx.hash}`); + } + + console.log( + `Adding Item Types Batch ${ + i + 1 + } of ${totalBatches}, gas used:: ${strDisplay(receipt.gasUsed)}` + ); + totalGasUsed = totalGasUsed.add(receipt.gasUsed); + } + console.log("Finished adding itemTypes"); + + // add wearable types sets + console.log("Adding ", wearableSetArrays.length, "Wearable Sets"); + step = 50; + totalBatches = Math.ceil(wearableSetArrays.length / step); + + for (let i = 0; i < totalBatches; i++) { + const start = step * i; + const end = start + step; + const batch = wearableSetArrays.slice(start, end); + + const tx = await daoFacet.addWearableSets(batch, { gasLimit: gasLimit }); + + const receipt = await tx.wait(); + console.log( + `Adding Wearable Sets Batch ${ + i + 1 + } of ${totalBatches}, gas used:: ${strDisplay(receipt.gasUsed)}` + ); + + if (!receipt.status) { + throw Error(`Error:: ${tx.hash}`); + } + + totalGasUsed = totalGasUsed.add(receipt.gasUsed); + } + + //add sideview dimensions in batches of 200 + step = 200; + console.log("adding", allSideViewDimensions.length, "sideviews"); + let sliceStep = Math.ceil(allSideViewDimensions.length / step); + + for (let i = 0; i < sliceStep; i++) { + const start = step * i; + const end = start + step; + const batch = allSideViewDimensions.slice(start, end); + console.log(`Adding Sideview Dimensions (${i + 1} / ${sliceStep})`); + await run( + "updateItemSideDimensions", + convertSideDimensionsToTaskFormat(batch, aavegotchiDiamond.address) + ); + } + + //add sideview exceptions in batches of 100 + step = 100; + console.log("adding", allExceptions.length, "exceptions"); + sliceStep = Math.ceil(allExceptions.length / step); + + for (let i = 0; i < sliceStep; i++) { + const start = sliceStep * i; + const end = start + sliceStep; + const slice = allExceptions.slice( + start, + Math.min(end, allExceptions.length) + ); + console.log(`Adding Sideview Exceptions (${i + 1} / ${sliceStep}) `); + const tx = await run( + "updateWearableExceptions", + convertExceptionsToTaskFormat(slice, aavegotchiDiamond.address) + ); + } + + console.log("Upload SVGs"); + + const { eyeShapeSvgs } = require("../svgs/eyeShapes.js"); + const collateralsSvgs = [ + '', + ]; + const collateralsLeftSvgs = [ + '', + ]; + const collateralsRightSvgs = [ + '', + ]; + + console.log("uploading portal svgs"); + await uploadSvgs(svgFacet, openedPortals, "portal-open", ethers); + await uploadSvgs(svgFacet, closedPortals, "portal-closed", ethers); + + console.log("uploading aavegotchiSvgs"); + await uploadSvgs(svgFacet, aavegotchiSvgs, "aavegotchi", ethers); + console.log("uploading collaterals"); + await uploadSvgs(svgFacet, collateralsSvgs, "collaterals", ethers); + console.log("uploading eyeShapes"); + await uploadSvgs(svgFacet, eyeShapeSvgs, "eyeShapes", ethers); + console.log("uploading aavegotchiSideSvgsLeft"); + await uploadSvgs( + svgFacet, + aavegotchiSideSvgs.left, + "aavegotchi-left", + ethers + ); + console.log("uploading aavegotchiSideSvgsRight"); + await uploadSvgs( + svgFacet, + aavegotchiSideSvgs.right, + "aavegotchi-right", + ethers + ); + console.log("uploading aavegotchiSideSvgsBack"); + await uploadSvgs( + svgFacet, + aavegotchiSideSvgs.back, + "aavegotchi-back", + ethers + ); + console.log("uploading collateral-side svgs"); + await uploadSvgs(svgFacet, collateralsLeftSvgs, "collaterals-left", ethers); + await uploadSvgs(svgFacet, collateralsRightSvgs, "collaterals-right", ethers); + await uploadSvgs(svgFacet, [""], "collaterals-back", ethers); + await uploadSvgs(svgFacet, eyeShapesLeftSvgs, "eyeShapes-left", ethers); + await uploadSvgs(svgFacet, eyeShapesRightSvgs, "eyeShapes-right", ethers); + await uploadSvgs( + svgFacet, + Array(eyeShapeSvgs.length).fill(""), + "eyeShapes-back", + ethers + ); + + const { sleeves, wearables } = getWearables(); + + const svgsArray: string[] = wearables; + const sleeveSvgsArray: SleeveObject[] = sleeves; + + console.log("Uploading wearables"); + await uploadSvgs(svgFacet, svgsArray, "wearables", ethers); + console.log("Uploading sleeves"); + await uploadSvgs( + svgFacet, + sleeveSvgsArray.map((value) => value.svg), + "sleeves", + ethers + ); + + //uploading sideviews + + console.log("Uploading wearablesleft"); + await uploadSvgs( + svgFacet, + wearablesLeftSvgs as string[], + "wearables-left", + ethers + ); + console.log("Uploading wearablesRight"); + await uploadSvgs( + svgFacet, + wearablesRightSvgs as string[], + "wearables-right", + ethers + ); + console.log("Uploading wearablesBack"); + await uploadSvgs( + svgFacet, + wearablesBackSvgs as string[], + "wearables-back", + ethers + ); + console.log("Uploading wearablesLeftSleeve"); + await uploadSvgs(svgFacet, wearablesLeftSleeveSvgs, "sleeves-left", ethers); + console.log("Uploading wearablesRightSleeve"); + await uploadSvgs(svgFacet, wearablesRightSleeveSvgs, "sleeves-right", ethers); + console.log("Uploading wearablesBackSleeve"); + await uploadSvgs(svgFacet, wearablesBackSleeveSvgs, "sleeves-back", ethers); + console.log("Upload Done"); + + interface SleeveInput { + sleeveId: BigNumberish; + wearableId: BigNumberish; + } + let sleevesSvgId: number = 0; // TODO + let sleevesInput: SleeveInput[] = []; + for (const sleeve of sleeveSvgsArray) { + sleevesInput.push({ + sleeveId: sleevesSvgId, + wearableId: sleeve.id, + }); + sleevesSvgId++; + } + + console.log("Associating sleeves svgs with body wearable svgs."); + tx = await svgFacet.setSleeves(sleevesInput); + receipt = await tx.wait(); + if (!receipt.status) { + throw Error(`Error:: ${tx.hash}`); + } + console.log("Sleeves associating gas used::" + strDisplay(receipt.gasUsed)); + totalGasUsed = totalGasUsed.add(receipt.gasUsed); + + await setForgeProperties(forgeDiamond.address); + tx = await daoFacet.setForge(forgeDiamond.address, { gasLimit: gasLimit }); + receipt = await tx.wait(); + console.log("Forge diamond set:" + strDisplay(receipt.gasUsed)); + totalGasUsed = totalGasUsed.add(receipt.gasUsed); + + // add erc721 and 1155 categories + // console.log("Adding ERC721 categories"); + // const erc721Categories = [ + // { + // erc721TokenAddress: realmDiamondAddress, + // category: 4, + // }, + // { + // erc721TokenAddress: fakeGotchiArtDiamondAddress, + // category: 5, + // }, + // ]; + // tx = await erc721MarketplaceFacet.setERC721Categories(erc721Categories, { + // gasLimit: gasLimit, + // }); + // receipt = await tx.wait(); + // if (!receipt.status) { + // throw Error(`Error:: ${tx.hash}`); + // } + // console.log( + // "Adding ERC721 categories gas used::" + strDisplay(receipt.gasUsed) + // ); + // totalGasUsed = totalGasUsed.add(receipt.gasUsed); + // + // console.log("Adding ERC1155 categories"); + // const erc1155Categories = []; + // for (let i = 0; i < 6; i++) { + // erc1155Categories.push({ + // erc1155TokenAddress: ghstStakingDiamondAddress, + // erc1155TypeId: i, + // category: 3, + // }); + // } + // [ + // 1, 141, 142, 143, 144, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, + // 156, + // ].forEach((id) => { + // erc1155Categories.push({ + // erc1155TokenAddress: installationDiamondAddress, + // erc1155TypeId: id, + // category: 4, + // }); + // }); + // Array.from({ length: 31 }, (_, index) => index + 1).forEach((id) => { + // erc1155Categories.push({ + // erc1155TokenAddress: tileDiamondAddress, + // erc1155TypeId: id, + // category: 5, + // }); + // }); + // erc1155Categories.push({ + // erc1155TokenAddress: fakeGotchiCardDiamondAddress, + // erc1155TypeId: 0, + // category: 6, + // }); + // + // const offset = 1_000_000_000; + // const alloyCategory = 7; + // const geodesCategory = 9; + // const essenceCategory = 10; + // const coresCategory = 11; + // const alloyIds = [offset]; + // const essenceIds = [offset + 1]; + // const geodeIds = []; //[offset + 2, offset +3, offset+4, offset+5, offset+6, offset+7]; + // for (let i = offset + 2; i < offset + 8; i++) { + // geodeIds.push(i); + // } + // const coreIds = []; + // for (let i = offset + 8; i < offset + 44; i++) { + // coreIds.push(i); + // } + // const forgeFinalArray = [ + // [alloyCategory, alloyIds], + // [geodesCategory, geodeIds], + // [essenceCategory, essenceIds], + // [coresCategory, coreIds], + // ]; + // forgeFinalArray.forEach((el) => { + // const category = el[0]; + // const toAdd = el[1] as number[]; + // + // for (let index = 0; index < toAdd.length; index++) { + // erc1155Categories.push({ + // erc1155TokenAddress: forgeDiamond.address, + // erc1155TypeId: toAdd[index], + // category: category, + // }); + // } + // }); + // + // tx = await erc1155MarketplaceFacet.setERC1155Categories(erc1155Categories, { + // gasLimit: gasLimit, + // }); + // receipt = await tx.wait(); + // if (!receipt.status) { + // throw Error(`Error:: ${tx.hash}`); + // } + // console.log( + // "Adding ERC1155 categories gas used::" + strDisplay(receipt.gasUsed) + // ); + // totalGasUsed = totalGasUsed.add(receipt.gasUsed); + // + // set realm address + // tx = await aavegotchiGameFacet.setRealmAddress(realmDiamondAddress, { + // gasLimit: gasLimit, + // }); + // receipt = await tx.wait(); + // console.log("Realm diamond set:" + strDisplay(receipt.gasUsed)); + // totalGasUsed = totalGasUsed.add(receipt.gasUsed); + + console.log("Total gas used: " + strDisplay(totalGasUsed)); +} + +// We recommend this pattern to be able to use async/await everywhere +// and properly handle errors. +if (require.main === module) { + main() + .then(() => process.exit(0)) + .catch((error) => { + console.error(error); + process.exit(1); + }); +} + +exports.deployProject = main; diff --git a/scripts/geistBridge/bridgeTest.ts b/scripts/geistBridge/bridgeTest.ts new file mode 100644 index 000000000..46f3c5c27 --- /dev/null +++ b/scripts/geistBridge/bridgeTest.ts @@ -0,0 +1,111 @@ +/* global ethers hre */ + +import { ethers, network } from "hardhat"; +import { maticDiamondAddress } from "../helperFunctions"; + +export default async function main() { + let diamondAddress; + let gotchiBridgeAddress; + let gotchiConnectorAddress; + let itemBridgeAddress; + let itemConnectorAddress; + if (network.name === "base-sepolia") { + diamondAddress = "0x87C969d083189927049f8fF3747703FB9f7a8AEd" + // vault address + gotchiBridgeAddress = "0x0e915A936d4a7E300B749112DA80D047Bf580DA7" + gotchiConnectorAddress = "0x06C845Df424C9DD61Eb4D59ceCa631b597CC3c5F" + itemBridgeAddress = "0xde94E671f4612D0F020851173e9fD99d3A6Cc9F3" + itemConnectorAddress = "0xff2b3CdaA9882b89c8d64a6904263A58c4644762" + } else if (network.name === "matic") { + diamondAddress = maticDiamondAddress + // TODO: connector address + gotchiBridgeAddress = "" + gotchiConnectorAddress = "" + itemBridgeAddress = "" + itemConnectorAddress = "" + } else { + throw Error("No network settings for " + network.name); + } + + const bridgeFacet = await ethers.getContractAt("PolygonXGeistBridgeFacet", diamondAddress) + const aavegotchiFacet = await ethers.getContractAt("contracts/Aavegotchi/facets/AavegotchiFacet.sol:AavegotchiFacet", diamondAddress) + const svgFacet = await ethers.getContractAt("SvgFacet", diamondAddress) + const daoFacet = await ethers.getContractAt("DAOFacet", diamondAddress) + const itemsFacet = await ethers.getContractAt("contracts/Aavegotchi/facets/ItemsFacet.sol:ItemsFacet", diamondAddress) + + const accounts = await ethers.getSigners(); + const signer = accounts[0]; + const gasLimit = 500000; + const gasPrice = 100000000000; + let tx; + + // console.log(`Trying to approve to send gotchis/items.`); + // tx = await aavegotchiFacet.setApprovalForAll(itemBridgeAddress, true) + // console.log(`Wating for tx to be validated, tx hash: ${tx.hash}`) + // await tx.wait() + + // aavegotchi bridging + for (let tokenId = 106; tokenId < 108; tokenId++) { + const gotchi = await aavegotchiFacet.getAavegotchi(tokenId) + console.log(`Gotchi: ${gotchi}`) + const svg = await svgFacet.getAavegotchiSvg(tokenId) + console.log(`Gotchi SVG: ${svg}`) + + console.log(`Trying to approve to send a gotchi. Token Id: ${tokenId}`); + tx = await aavegotchiFacet.approve(gotchiBridgeAddress, tokenId) + console.log(`Wating for tx to be validated, tx hash: ${tx.hash}`) + await tx.wait() + + console.log(`Trying to bridge a gotchi. Token Id:${tokenId}`); + tx = await bridgeFacet.bridgeGotchi(signer.address, tokenId, gasLimit, gotchiConnectorAddress, {gasPrice: gasPrice}) + console.log(`Wating for tx to be validated, tx hash: ${tx.hash}`) + await tx.wait() + } + + // item minting + // const mintTokenIds = [151, 152, 153, 210]; + // const quantities = [20, 20, 20, 20]; + // console.log(`Trying to mint items...`) + // tx = await daoFacet.mintItems(signer.address, mintTokenIds, quantities, {gasPrice: gasPrice}) + // console.log(`Wating for tx to be validated, tx hash: ${tx.hash}`) + // await tx.wait() + + // item bridging + // for (let tokenId = 1; tokenId < 30; tokenId++) { + // console.log(`Trying to bridge an item. Item Id:${tokenId}`) + // tx = await bridgeFacet.bridgeItem(signer.address, tokenId, 2, gasLimit, itemConnectorAddress, {gasPrice: gasPrice}) + // console.log(`Wating for tx to be validated, tx hash: ${tx.hash}`) + // await tx.wait() + // } + + // equip/unequip gotchi + // for (let tokenId = 106; tokenId < 107; tokenId++) { + // console.log(`Trying to equip/unequip a gotchi. Token Id: ${tokenId}`); + // // // equip all slots + // // tx = await itemsFacet.equipWearables(tokenId, [15, 13, 14, 10, 29, 12, 151, 0, 0, 0, 0, 0, 0, 0, 0, 0]) + // // equip some slots + // tx = await itemsFacet.equipWearables(tokenId, [15, 0, 14, 0, 29, 0, 151, 0, 0, 0, 0, 0, 0, 0, 0, 0]) + // // // unequip all + // // tx = await itemsFacet.equipWearables(tokenId, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) + // console.log(`Wating for tx to be validated, tx hash: ${tx.hash}`) + // await tx.wait() + // } + + // check code + // console.log(`Fetching information of gotchis. Owner address:${signer.address}`); + // const gotchis = await aavegotchiFacet.allAavegotchisOfOwner(signer.address) + // console.log(`Gotchis: ${gotchis}`) +} + +// We recommend this pattern to be able to use async/await everywhere +// and properly handle errors. +if (require.main === module) { + main() + .then(() => process.exit(0)) + .catch((error) => { + console.error(error); + process.exit(1); + }); +} + +exports.deployProject = main; diff --git a/scripts/geistBridge/configureBridge.ts b/scripts/geistBridge/configureBridge.ts new file mode 100644 index 000000000..4e1abae17 --- /dev/null +++ b/scripts/geistBridge/configureBridge.ts @@ -0,0 +1,57 @@ +/* global ethers hre */ + +import { ethers, network } from "hardhat"; +import { maticDiamondAddress } from "../helperFunctions"; +import { AMOY_DIAMOND } from "../../helpers/constants"; + +export default async function main() { + const gasPrice = "70000000000"; + let gotchiBridgeAddress; + let itemBridgeAddress; + let diamondAddress; + let tx; + if (network.name === "base-sepolia") { + diamondAddress = "0x87C969d083189927049f8fF3747703FB9f7a8AEd"; + // vault address + gotchiBridgeAddress = "0x0e915A936d4a7E300B749112DA80D047Bf580DA7"; + itemBridgeAddress = "0xde94E671f4612D0F020851173e9fD99d3A6Cc9F3"; + } else if (network.name === "matic") { + diamondAddress = maticDiamondAddress; + // TODO: vault address + gotchiBridgeAddress = ""; + itemBridgeAddress = ""; + } else { + throw Error("No network settings for " + network.name); + } + + const daoFacet = await ethers.getContractAt("DAOFacet", diamondAddress); + + console.log(`Configuring gotchi bridge...`); + tx = await daoFacet.updateGotchiGeistBridge(gotchiBridgeAddress, { + gasPrice: gasPrice, + }); + console.log(`Wating for tx to be validated, tx hash: ${tx.hash}`); + await tx.wait(); + + console.log(`Configuring items bridge...`); + tx = await daoFacet.updateItemGeistBridge(itemBridgeAddress, { + gasPrice: gasPrice, + }); + console.log(`Wating for tx to be validated, tx hash: ${tx.hash}`); + await tx.wait(); + + console.log(`Bridge configured on ${network.name}.`); +} + +// We recommend this pattern to be able to use async/await everywhere +// and properly handle errors. +if (require.main === module) { + main() + .then(() => process.exit(0)) + .catch((error) => { + console.error(error); + process.exit(1); + }); +} + +exports.deployProject = main; diff --git a/scripts/helperFunctions.ts b/scripts/helperFunctions.ts index f00721555..0eef1affd 100644 --- a/scripts/helperFunctions.ts +++ b/scripts/helperFunctions.ts @@ -287,9 +287,8 @@ export async function getRelayerSigner(hre: HardhatRuntimeEnvironment) { speed: "safeLow", validForSeconds: 7200, }); - } else if (hre.network.name === "tenderly") { + } else if (["tenderly", "base-sepolia", "amoy"].includes(hre.network.name)) { //impersonate - console.log("Using tenderly"); return (await hre.ethers.getSigners())[0]; } else { throw Error("Incorrect network selected"); diff --git a/scripts/itemTypeHelpers.ts b/scripts/itemTypeHelpers.ts index 96d2be8f3..8e00ae26c 100644 --- a/scripts/itemTypeHelpers.ts +++ b/scripts/itemTypeHelpers.ts @@ -24,11 +24,7 @@ export interface SideDimensions { export interface Exceptions { itemId: BigNumberish; slotPosition: BigNumberish; - side: - | "wearables-back" - | "wearables-left" - | "wearables-right" - | "wearables-front"; + side: string; exceptionBool: boolean; } @@ -80,19 +76,6 @@ export type rarityLevel = | "mythical" | "godlike"; -export type Author = - | "GFA" - | "z_tef" - | "Laggin" - | "XIBOT" - | "xibot" - | "oggysk" - | "Oliver Spoon" - | "[GFA] z_tef" - | "THE FORGE" - | "soju" - | "SOJU"; - export interface ItemTypeInputNew { name: string; description: string; @@ -101,7 +84,7 @@ export interface ItemTypeInputNew { canBeTransferred: boolean; rarityLevel: rarityLevel; setId: BigNumberish[]; - author: Author; + author: string; dimensions: Dimensions; allowedCollaterals: BigNumberish[]; ghstPrice: BigNumberish | BigNumberish; @@ -123,6 +106,30 @@ export interface ItemTypeInputNew { maxQuantity?: number; } +export function toItemTypeInputNew(item: ItemTypeInput): ItemTypeInputNew { + return { + name: item.name, + description: item.description, + svgId: item.svgId, + minLevel: item.minLevel, + canBeTransferred: item.canBeTransferred, + rarityLevel: maxQuantityToRarity(Number(item.maxQuantity)), + setId: item.setId, + author: item.author, + dimensions: item.dimensions, + allowedCollaterals: item.allowedCollaterals, + ghstPrice: item.ghstPrice, + traitModifiers: item.traitModifiers, + slotPositions: item.slotPositions, + category: item.category, + experienceBonus: item.experienceBonus, + kinshipBonus: item.kinshipBonus, + canPurchaseWithGhst: item.canPurchaseWithGhst, + maxQuantity: Number(item.maxQuantity), + totalQuantity: Number(item.totalQuantity), + }; +} + export interface ItemTypeOutput { name: string; description: string; @@ -389,8 +396,8 @@ export function stringToSlotPositions( false, false, false, - true, false, + true, false, false, false, @@ -434,6 +441,9 @@ export function calculateRarityScoreModifier(maxQuantity: number): number { return 0; } +//exclude some tems from traitBooster checklist +const excludedItems = [0, 26, 100, 105, 126, 127, 128, 129]; + export function getItemTypes( itemTypes: ItemTypeInputNew[], ethers: any @@ -458,9 +468,14 @@ export function getItemTypes( Number(prev) + Math.abs(Number(cur)); let traitBoosters = itemType.traitModifiers.reduce(reducer, 0); - if (itemType.category !== 1) { + if ( + itemType.category !== 1 && + !excludedItems.includes(Number(itemType.svgId)) + ) { if (traitBoosters !== rarityLevelToTraitBoosters(itemType.rarityLevel)) { - throw Error(`Trait Booster for ${itemType.name} does not match rarity`); + throw Error( + `Trait Booster for ${itemType.name} does not match rarity` + ); } } @@ -540,6 +555,15 @@ function rarityLevelToMaxQuantity(rarityLevel: rarityLevel): number { } } +export function maxQuantityToRarity(quantity: number) { + if (quantity >= 1000) return "common"; + else if (quantity >= 500) return "uncommon"; + else if (quantity >= 250) return "rare"; + else if (quantity >= 100) return "legendary"; + else if (quantity >= 10) return "mythical"; + else return "godlike"; +} + export function rarityLevelToTraitBoosters(rarityLevel: rarityLevel): number { switch (rarityLevel) { case "common": diff --git a/scripts/testCollateralTypes.js b/scripts/testCollateralTypes.js index b57ae5150..43e17c694 100644 --- a/scripts/testCollateralTypes.js +++ b/scripts/testCollateralTypes.js @@ -1,20 +1,19 @@ - const collaterals = [ - { - name: 'GHST', - kovanAddress: '', - mainnetAddress: '', - hardhatAddress: '', - mumbaiAddress: '', - primaryColor: '#FF7D00', - secondaryColor: '#F9D792', - cheekColor: '#F4AF24', + name: "GHST", + kovanAddress: "", + mainnetAddress: "", + hardhatAddress: "", + mumbaiAddress: "", + amoyAddress: "0xF679b8D109b2d23931237Ce948a7D784727c0897", + primaryColor: "#FF7D00", + secondaryColor: "#F9D792", + cheekColor: "#F4AF24", svgId: 0, eyeShapeSvgId: 16, modifiers: [0, 0, -1, 0, 0, 0], - conversionRate: 1 // 1 DAI equals 1 DAI - } + conversionRate: 1, // 1 DAI equals 1 DAI + }, /* { @@ -31,54 +30,69 @@ const collaterals = [ conversionRate: 1 // 1 DAI equals 1 DAI }, */ -] +]; -function eightBitArrayToUint (array) { - const uint = [] +function eightBitArrayToUint(array) { + const uint = []; for (const num of array) { - const value = ethers.BigNumber.from(num).toTwos(8) - uint.unshift(value.toHexString().slice(2)) + const value = ethers.BigNumber.from(num).toTwos(8); + uint.unshift(value.toHexString().slice(2)); } - return ethers.BigNumber.from('0x' + uint.join('')) + return ethers.BigNumber.from("0x" + uint.join("")); } -function getCollaterals (network, ghstAddress, testAddress) { - const collateralTypes = [] +function getCollaterals(network, ghstAddress) { + const collateralTypes = []; for (const collateralType of collaterals) { const collateralTypeInfo = { - primaryColor: - '0x' + collateralType.primaryColor.slice(1), - secondaryColor: - '0x' + collateralType.secondaryColor.slice(1), - cheekColor: - '0x' + collateralType.cheekColor.slice(1), + primaryColor: "0x" + collateralType.primaryColor.slice(1), + secondaryColor: "0x" + collateralType.secondaryColor.slice(1), + cheekColor: "0x" + collateralType.cheekColor.slice(1), svgId: collateralType.svgId, eyeShapeSvgId: collateralType.eyeShapeSvgId, // modifiers: eightBitArrayToUint(collateralType.modifiers), modifiers: collateralType.modifiers, conversionRate: collateralType.conversionRate, - delisted: false + delisted: false, + }; + const item = {}; + if (network === "kovan") { + item.collateralType = collateralType.kovanAddress; + } else if (network === "mumbai") { + item.collateralType = ghstAddress; + } else if (network === "hardhat" || network === "localhost") { + item.collateralType = ghstAddress; + // else if (collateralType.name === "TEST") + // item.collateralType = testAddress; + } else if (network === "mainnet") { + item.collateralType = collateralType.mainnetAddress; + } else if (network === "matic") { + item.collateralTypeInfo = collateralType.maticAddress; + } else if (network === "amoy") { + item.collateralTypeInfo = collateralType.amoyAddress; } - const item = {} - if (network === 'kovan') { - item.collateralType = collateralType.kovanAddress - } else if (network === 'mumbai') { - if (collateralType.name === 'GHST') { - item.collateralType = ghstAddress - } - } else if (network === 'hardhat') { - if (collateralType.name === 'GHST') item.collateralType = ghstAddress - else if (collateralType.name === 'TEST') item.collateralType = testAddress - } else if (network === 'mainnet') { - item.collateralType = collateralType.mainnetAddress - } else if (network === 'matic') { - item.collateralTypeInfo = collateralType.maticAddress - } - item.collateralTypeInfo = collateralTypeInfo - collateralTypes.push(item) + item.collateralTypeInfo = collateralTypeInfo; + collateralTypes.push(item); } - - return collateralTypes } -exports.getCollaterals = getCollaterals +//for rough tests only +const collateralTypeInfo = [ + { + collateralType: "0xF679b8D109b2d23931237Ce948a7D784727c0897", + collateralTypeInfo: { + primaryColor: "0x" + "#FF7D00".slice(1), + secondaryColor: "0x" + "#F9D792".slice(1), + cheekColor: "0x" + "#F4AF24".slice(1), + svgId: 0, + eyeShapeSvgId: 16, + modifiers: [0, 0, -1, 0, 0, 0], + conversionRate: 1, // 1 DAI equals 1 DAI + delisted: true, + }, + }, +]; + +exports.collaterals = collateralTypeInfo; + +//exports.getCollaterals = getCollaterals; diff --git a/scripts/updates/batchMintGotchigangWearables.ts b/scripts/updates/batchMintGotchigangWearables.ts index 554d24a7e..7dd42472c 100644 --- a/scripts/updates/batchMintGotchigangWearables.ts +++ b/scripts/updates/batchMintGotchigangWearables.ts @@ -14,7 +14,6 @@ import { } from "../../typechain"; import { LedgerSigner } from "@anders-t/ethers-ledger"; import * as helpers from "@nomicfoundation/hardhat-network-helpers"; -import { WEARABLE_BASE_QUANTITIES } from "../../helpers/constants"; export const forgeAddresses = [ "0x4a478E4593A5D557dB640642c34Ae52800084451", @@ -133,13 +132,7 @@ export async function batchMintGotchigangWearables() { signer )) as ForgeFacet; - const totalAmounts = [ - WEARABLE_BASE_QUANTITIES.COMMON, - WEARABLE_BASE_QUANTITIES.UNCOMMON, - WEARABLE_BASE_QUANTITIES.RARE, - WEARABLE_BASE_QUANTITIES.LEGENDARY, - WEARABLE_BASE_QUANTITIES.MYTHICAL, - ]; + const totalAmounts = [1000, 500, 250, 100, 10]; const ids = Object.values(itemIds).flat(); const amounts = Object.entries(itemIds).flatMap(([rarity, ids]) => diff --git a/scripts/upgrades/upgrade-erc1155BuyOrderFacet.ts b/scripts/upgrades/upgrade-erc1155BuyOrderFacet.ts index d8aac7387..ebb7c7642 100644 --- a/scripts/upgrades/upgrade-erc1155BuyOrderFacet.ts +++ b/scripts/upgrades/upgrade-erc1155BuyOrderFacet.ts @@ -5,6 +5,9 @@ import { FacetsAndAddSelectors, } from "../../tasks/deployUpgrade"; import { maticDiamondAddress, maticDiamondUpgrader } from "../helperFunctions"; +import { AMOY_DIAMON_OWNER, AMOY_DIAMOND } from "../../helpers/constants"; + +export async function upgrade() { export async function upgrade() { @@ -19,6 +22,8 @@ export async function upgrade() { removeSelectors: [], }, { + facetName: + "contracts/Aavegotchi/facets/ERC1155MarketplaceFacet.sol:ERC1155MarketplaceFacet", facetName: "ERC1155MarketplaceFacet", addSelectors: [], removeSelectors: [], @@ -28,6 +33,11 @@ export async function upgrade() { const joined = convertFacetAndSelectorsToString(facets); const args: DeployUpgradeTaskArgs = { + diamondOwner: AMOY_DIAMON_OWNER, + diamondAddress: AMOY_DIAMOND, + facetsAndAddSelectors: joined, + useLedger: false, + useMultisig: false, diamondOwner: maticDiamondUpgrader, diamondAddress: maticDiamondAddress, facetsAndAddSelectors: joined, diff --git a/scripts/upgrades/upgrade-geistBridgeFacet.ts b/scripts/upgrades/upgrade-geistBridgeFacet.ts new file mode 100644 index 000000000..4b0e48069 --- /dev/null +++ b/scripts/upgrades/upgrade-geistBridgeFacet.ts @@ -0,0 +1,57 @@ +import { ethers, run } from "hardhat"; +import { + convertFacetAndSelectorsToString, + DeployUpgradeTaskArgs, + FacetsAndAddSelectors, +} from "../../tasks/deployUpgrade"; +import { maticDiamondAddress } from "../helperFunctions"; + +export async function upgrade() { + const diamondOwner = "0x01F010a5e001fe9d6940758EA5e8c777885E351e"; + + const facets: FacetsAndAddSelectors[] = [ + { + facetName: "PolygonXGeistBridgeFacet", + addSelectors: [ + "function bridgeGotchi(address _receiver, uint256 _tokenId, uint256 _msgGasLimit, address _connector) external payable", + "function setMetadata(uint _tokenId, bytes memory _metadata) external", + "function bridgeItem(address _receiver, uint256 _tokenId, uint256 _amount, uint256 _msgGasLimit, address _connector) external payable", + ], + removeSelectors: [], + }, + { + facetName: "DAOFacet", + addSelectors: [ + "function updateGotchiGeistBridge(address _newBridge) external", + "function updateItemGeistBridge(address _newBridge) external", + ], + removeSelectors: [], + }, + ]; + + const joined = convertFacetAndSelectorsToString(facets); + + const args: DeployUpgradeTaskArgs = { + // diamondOwner: AMOY_DIAMOND_OWNER, + // diamondAddress: AMOY_DIAMOND, + diamondOwner: '0xd38Df837a1EAd12ee16f8b8b7E5F58703f841668', + diamondAddress: '0x87C969d083189927049f8fF3747703FB9f7a8AEd', // base-sepolia + facetsAndAddSelectors: joined, + useLedger: false, + useMultisig: false, + initAddress: ethers.constants.AddressZero, + initCalldata: "0x", + }; + + await run("deployUpgrade", args); +} + +if (require.main === module) { + upgrade() + .then(() => process.exit(0)) + // .then(() => console.log('upgrade completed') /* process.exit(0) */) + .catch((error) => { + console.error(error); + process.exit(1); + }); +} diff --git a/svgs/aavegotchi.js b/svgs/aavegotchi.js deleted file mode 100644 index 443921a53..000000000 --- a/svgs/aavegotchi.js +++ /dev/null @@ -1,29 +0,0 @@ -const fs = require('fs') -const sealedClosedPortal = fs.readFileSync('./svgs/sealedClosedPortal.svg', 'utf8') -const openPortal = fs.readFileSync('./svgs/openPortal.svg', 'utf8') - -const body = '' -const cheeks = '' -const mouth = '' -const handsDownClosed = '' -const handsDownOpen = '' -const handsUp = '' -const shadow = '' -const aavegotchiBody = body + cheeks + mouth + shadow -const hands = handsDownClosed + handsDownOpen + handsUp -const aavegotchiSvgs = [ - // 0, sealed closed portal - sealedClosedPortal, - // 1, open portal - openPortal, - // 2 aavegotchi - aavegotchiBody, - // 3 hands - hands, - - // 4 Background ETH - - '' -] - -exports.aavegotchiSvgs = aavegotchiSvgs diff --git a/svgs/aavegotchi.ts b/svgs/aavegotchi.ts new file mode 100644 index 000000000..b09b4f254 --- /dev/null +++ b/svgs/aavegotchi.ts @@ -0,0 +1,37 @@ +const fs = require("fs"); +import { closedPortals } from "./portals"; + +const openPortal = fs.readFileSync("./svgs/openPortal.svg", "utf8"); + +const body = + ''; +const cheeks = + ''; +const mouth = + ''; +const handsDownClosed = + ''; +const handsDownOpen = + ''; +const handsUp = + ''; +const shadow = + ''; +const aavegotchiBody = body + cheeks + mouth + shadow; +const hands = handsDownClosed + handsDownOpen + handsUp; +export const aavegotchiSvgs = [ + // 0, sealed closed portal + ...closedPortals, + // 1, open portal + openPortal, + // 2 aavegotchi + aavegotchiBody, + // 3 hands + hands, + + // 4 Background ETH + + '', +]; + +exports.aavegotchiSvgs = aavegotchiSvgs; diff --git a/svgs/closedPortalSvg.js b/svgs/closedPortalSvg.js deleted file mode 100644 index 35c66fd16..000000000 --- a/svgs/closedPortalSvg.js +++ /dev/null @@ -1,29 +0,0 @@ -/* eslint-disable prefer-const */ - -const fs = require("fs"); - -const portals = []; - -portal("h1-closed"); -portal("h1-closed"); -portal("h2-closed"); - -function stripSvg(svg) { - // removes svg tag - if (svg.includes("viewBox")) { - svg = svg.slice(svg.indexOf(">") + 1); - svg = svg.replace("", ""); - } - return svg; -} - -function readSvg(name) { - return stripSvg(fs.readFileSync(`./svgs/${name}.svg`, "utf8")); -} - -function portal(name) { - const svg = readSvg(name); - portals.push(svg); -} - -exports.closedPortalSvgs = portals; diff --git a/svgs/portals.ts b/svgs/portals.ts new file mode 100644 index 000000000..f22020c0c --- /dev/null +++ b/svgs/portals.ts @@ -0,0 +1,35 @@ +/* eslint-disable prefer-const */ + +const fs = require("fs"); + +export const closedPortals: string[] = []; + +export const openedPortals: string[] = []; + +portal("h1-closed", true); +portal("h2-closed", true); + +portal("h1-open", false); +portal("h2-open", false); + +function stripSvg(svg: string) { + // removes svg tag + if (svg.includes("viewBox")) { + svg = svg.slice(svg.indexOf(">") + 1); + svg = svg.replace("", ""); + } + return svg; +} + +function readSvg(name: string) { + return stripSvg(fs.readFileSync(`./svgs/${name}.svg`, "utf8")); +} + +function portal(name: string, closed: boolean) { + const svg: string = readSvg(name); + if (closed) { + closedPortals.push(svg); + } else { + openedPortals.push(svg); + } +} diff --git a/tasks/deployUpgrade.ts b/tasks/deployUpgrade.ts index 316ba127d..e664f46d3 100644 --- a/tasks/deployUpgrade.ts +++ b/tasks/deployUpgrade.ts @@ -154,7 +154,11 @@ task( }); signer = await hre.ethers.getSigner(owner); - } else if (hre.network.name === "matic") { + } else if ( + hre.network.name === "matic" || + hre.network.name === "base-sepolia" || + hre.network.name === "amoy" + ) { if (useLedger) { signer = new LedgerSigner(hre.ethers.provider, "m/44'/60'/1'/0/0"); } else signer = (await hre.ethers.getSigners())[0]; diff --git a/tasks/updateItemSideDimensions.ts b/tasks/updateItemSideDimensions.ts index 621e78435..1e501a5a7 100644 --- a/tasks/updateItemSideDimensions.ts +++ b/tasks/updateItemSideDimensions.ts @@ -19,10 +19,12 @@ export interface UpdateItemSideDimensionsTaskArgs { itemIds: string; sides: string; dimensions: string; + diamondAddress: string; } export function convertSideDimensionsToTaskFormat( - dimensions: SideDimensions[] + dimensions: SideDimensions[], + diamondAddress: string ) { const items: SideDimensions[] = []; for (let index = 0; index < dimensions.length; index++) { @@ -34,6 +36,7 @@ export function convertSideDimensionsToTaskFormat( dimensions: convertDimensionsArrayToString( items.map((item) => item.dimensions) ), + diamondAddress }; return sideDimensionsTaskArgs; } @@ -69,7 +72,7 @@ task( .addParam("itemIds", "Item IDs to update dimensions") .addParam("sides", "Item side to be updated dimensions") .addParam("dimensions", "New dimensions of each item") - + .addOptionalParam("diamondAddress", "Diamond address to update", maticDiamondAddress) .setAction( async ( taskArgs: UpdateItemSideDimensionsTaskArgs, @@ -85,7 +88,7 @@ task( const signer: Signer = await getRelayerSigner(hre); const svgViewsFacet = (await hre.ethers.getContractAt( "SvgViewsFacet", - maticDiamondAddress, + taskArgs.diamondAddress, signer )) as SvgViewsFacet; diff --git a/tasks/updateWearableExceptions.ts b/tasks/updateWearableExceptions.ts index f5fb33602..2ff932259 100644 --- a/tasks/updateWearableExceptions.ts +++ b/tasks/updateWearableExceptions.ts @@ -16,9 +16,10 @@ export interface UpdateExceptionTaskArg { slotPositions: string; sides: string; exceptionBools: string; + diamondAddress: string; } -export function convertExceptionsToTaskFormat(exceptions: Exceptions[]) { +export function convertExceptionsToTaskFormat(exceptions: Exceptions[], diamondAddress: string) { const items: Exceptions[] = []; for (let index = 0; index < exceptions.length; index++) { items.push(exceptions[index]); @@ -28,6 +29,7 @@ export function convertExceptionsToTaskFormat(exceptions: Exceptions[]) { slotPositions: items.map((item: Exceptions) => item.slotPosition).join(), sides: items.map((item: Exceptions) => item.side).join(), exceptionBools: items.map((item: Exceptions) => item.exceptionBool).join(), + diamondAddress }; console.log("Task Arg: ", exceptionsTaskArg); @@ -74,6 +76,7 @@ task( "exceptionBools", "Determines whether or not wearble ID is exception" ) + .addOptionalParam("diamondAddress", "Diamond address to update", maticDiamondAddress) .setAction( async ( @@ -91,7 +94,7 @@ task( const signer: Signer = await getRelayerSigner(hre); const svgViewsFacet = (await hre.ethers.getContractAt( "SvgViewsFacet", - maticDiamondAddress, + taskArgs.diamondAddress, signer )) as SvgViewsFacet;