Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 118 additions & 0 deletions contracts/Aavegotchi/facets/BuyOrderSwapFacet.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.1;

import {LibAppStorage, AppStorage} from "../libraries/LibAppStorage.sol";
import {LibTokenSwap} from "../libraries/LibTokenSwap.sol";
import {LibBuyOrder} from "../libraries/LibBuyOrder.sol";
import {IERC20} from "../../shared/interfaces/IERC20.sol";
import {Modifiers} from "../libraries/LibAppStorage.sol";

contract BuyOrderSwapFacet is Modifiers {
struct ERC1155SwapParams {
address tokenIn;
uint256 swapAmount;
uint256 minGhstOut;
uint256 swapDeadline;
uint256 buyOrderId;
address erc1155TokenAddress;
uint256 erc1155TokenId;
uint256 category;
uint256 priceInWei;
uint256 quantity;
uint256 duration;
address recipient;
}

struct ERC721SwapParams {
address tokenIn;
uint256 swapAmount;
uint256 minGhstOut;
uint256 swapDeadline;
uint256 buyOrderId;
address erc721TokenAddress;
uint256 erc721TokenId;
uint256 category;
uint256 priceInWei;
uint256 duration;
address recipient;
}

event SwapAndPlaceERC1155BuyOrder(address indexed buyer, uint256 indexed buyOrderId, address indexed tokenIn, uint256 ghstReceived);
event SwapAndPlaceERC721BuyOrder(address indexed buyer, uint256 indexed buyOrderId, address indexed tokenIn, uint256 ghstReceived);

/**
* @notice Swap tokens for GHST and immediately place a new ERC1155 buy order
* @param params Packed swap and order parameters
*/
function swapAndPlaceERC1155BuyOrder(ERC1155SwapParams calldata params) external payable whenNotPaused {
LibTokenSwap.validateSwapParams(params.tokenIn, params.swapAmount, params.minGhstOut, params.swapDeadline);
uint256 totalCost = LibBuyOrder.validateERC1155Params(params.erc1155TokenAddress, params.erc1155TokenId, params.priceInWei, params.quantity);

//assert ghst to be swapped to is enough
require(params.minGhstOut >= totalCost, "ERC1155BuyOrderSwap: minGhstOut must cover total cost");

uint256 initialBalance = IERC20(s.ghstContract).balanceOf(address(this));

//perform swap
uint256 ghstReceived = LibTokenSwap.swapForGHST(params.tokenIn, params.swapAmount, params.minGhstOut, params.swapDeadline, address(this));

//make sure we have received enough ghst
require(ghstReceived >= totalCost, "ERC1155BuyOrderSwap: Insufficient GHST for purchase");

//place buy order
LibBuyOrder._placeERC1155BuyOrder(
params.erc1155TokenAddress,
params.erc1155TokenId,
params.category,
params.priceInWei,
params.quantity,
params.duration
);

// Refund any excess GHST to the recipient using shared library, leave totalCost in the diamond
LibTokenSwap.refundExcessGHST(params.recipient, initialBalance + totalCost);

emit SwapAndPlaceERC1155BuyOrder(msg.sender, params.buyOrderId, params.tokenIn, ghstReceived);
Copy link

Copilot AI Sep 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The buyOrderId parameter is used in the event emission but it's not set during the function execution. The actual buyOrderId is generated inside LibBuyOrder._placeERC1155BuyOrder and LibBuyOrder._placeERC721BuyOrder functions, but those values are not returned or captured here.

Copilot uses AI. Check for mistakes.
}

/**
* @notice Swap tokens for GHST and immediately place a new ERC721 buy order
* @param params Packed swap and order parameters
* @param validationOptions Flags that determine additional validation logic
*/
function swapAndPlaceERC721BuyOrder(ERC721SwapParams calldata params, bool[] calldata validationOptions) external payable whenNotPaused {
LibTokenSwap.validateSwapParams(params.tokenIn, params.swapAmount, params.minGhstOut, params.swapDeadline);
uint256 totalCost = LibBuyOrder.validateERC721Params(
params.erc721TokenAddress,
params.erc721TokenId,
params.category,
params.priceInWei,
validationOptions
);

require(params.minGhstOut >= totalCost, "ERC721BuyOrderSwap: minGhstOut must cover total cost");

uint256 initialBalance = IERC20(s.ghstContract).balanceOf(address(this));

//perform swap
uint256 ghstReceived = LibTokenSwap.swapForGHST(params.tokenIn, params.swapAmount, params.minGhstOut, params.swapDeadline, address(this));

//make sure we have received enough ghst
require(ghstReceived >= totalCost, "ERC721BuyOrderSwap: Insufficient GHST for purchase");

//place buy order
LibBuyOrder._placeERC721BuyOrder(
params.erc721TokenAddress,
params.erc721TokenId,
params.category,
params.priceInWei,
params.duration,
validationOptions
);

// Refund any excess GHST to the recipient using shared library, leave totalCost in the diamond
LibTokenSwap.refundExcessGHST(params.recipient, initialBalance + totalCost);

emit SwapAndPlaceERC721BuyOrder(msg.sender, params.buyOrderId, params.tokenIn, ghstReceived);
Copy link

Copilot AI Sep 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The buyOrderId parameter is used in the event emission but it's not set during the function execution. The actual buyOrderId is generated inside LibBuyOrder._placeERC1155BuyOrder and LibBuyOrder._placeERC721BuyOrder functions, but those values are not returned or captured here.

Copilot uses AI. Check for mistakes.
}
}
48 changes: 2 additions & 46 deletions contracts/Aavegotchi/facets/ERC1155BuyOrderFacet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,6 @@ import {BaazaarSplit, LibSharedMarketplace, SplitAddresses} from "../libraries/L
import "../WearableDiamond/interfaces/IEventHandlerFacet.sol";

contract ERC1155BuyOrderFacet is Modifiers {
event ERC1155BuyOrderAdd(
uint256 indexed buyOrderId,
address indexed buyer,
address erc1155TokenAddress,
uint256 erc1155TokenId,
uint256 indexed category,
uint256 priceInWei,
uint256 quantity,
uint256 duration,
uint256 time
);
event ERC1155BuyOrderCancel(uint256 indexed buyOrderId, uint256 time);
event ERC1155BuyOrderExecute(
uint256 indexed buyOrderId,
Expand All @@ -46,13 +35,7 @@ contract ERC1155BuyOrderFacet is Modifiers {
uint256 _quantity,
uint256 _duration
) external whenNotPaused {
uint256 cost = _quantity * _priceInWei;
require(cost >= 1e15, "ERC1155BuyOrder: cost should be 0.001 GHST or larger");

require(LibSharedMarketplace.isContractWhitelisted(_erc1155TokenAddress), "ERC1155BuyOrder: contract not whitelisted");

require(!LibSharedMarketplace.isERC1155ListingExcluded(_erc1155TokenAddress, _erc1155TokenId), "ERC1155BuyOrder: token excluded");

uint256 cost = LibBuyOrder.validateERC1155Params(_erc1155TokenAddress, _erc1155TokenId, _priceInWei, _quantity);
address sender = LibMeta.msgSender();
uint256 ghstBalance = IERC20(s.ghstContract).balanceOf(sender);

Expand All @@ -62,34 +45,7 @@ contract ERC1155BuyOrderFacet is Modifiers {
LibERC20.transferFrom(s.ghstContract, sender, address(this), cost);

// Place new buy order
s.nextERC1155BuyOrderId++;
uint256 buyOrderId = s.nextERC1155BuyOrderId;

s.erc1155BuyOrders[buyOrderId] = ERC1155BuyOrder({
buyOrderId: buyOrderId,
buyer: sender,
erc1155TokenAddress: _erc1155TokenAddress,
erc1155TokenId: _erc1155TokenId,
category: _category,
priceInWei: _priceInWei,
quantity: _quantity,
timeCreated: block.timestamp,
lastTimePurchased: 0,
duration: _duration,
completed: false,
cancelled: false
});
emit ERC1155BuyOrderAdd(
buyOrderId,
sender,
_erc1155TokenAddress,
_erc1155TokenId,
_category,
_priceInWei,
_quantity,
_duration,
block.timestamp
);
LibBuyOrder._placeERC1155BuyOrder(_erc1155TokenAddress, _erc1155TokenId, _category, _priceInWei, _quantity, _duration);
}

function cancelERC1155BuyOrder(uint256 _buyOrderId) external whenNotPaused {
Expand Down
74 changes: 5 additions & 69 deletions contracts/Aavegotchi/facets/ERC721BuyOrderFacet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,6 @@ import {BaazaarSplit, LibSharedMarketplace, SplitAddresses} from "../libraries/L
import {CollateralEscrow} from "../CollateralEscrow.sol";

contract ERC721BuyOrderFacet is Modifiers {
event ERC721BuyOrderAdded(
uint256 indexed buyOrderId,
address indexed buyer,
address erc721TokenAddress,
uint256 erc721TokenId,
uint256 indexed category,
uint256 priceInWei,
uint256 duration,
bytes32 validationHash,
uint256 time
);
event ERC721BuyOrderCanceled(uint256 indexed buyOrderId, uint256 time);
event ERC721BuyOrderExecuted(
uint256 indexed buyOrderId,
address indexed buyer,
Expand Down Expand Up @@ -92,71 +80,19 @@ contract ERC721BuyOrderFacet is Modifiers {
uint256 _duration,
bool[] calldata _validationOptions // 0: BRS, 1: GHST, 2: skill points
) external whenNotPaused {
require(_priceInWei >= 1e18, "ERC721BuyOrder: price should be 1 GHST or larger");
// require(_priceInWei >= 1e18, "ERC721BuyOrder: price should be 1 GHST or larger");

Copy link

Copilot AI Sep 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Remove commented out code instead of leaving it in place. The validation has been moved to LibBuyOrder.validateERC721Params.

Suggested change
// require(_priceInWei >= 1e18, "ERC721BuyOrder: price should be 1 GHST or larger");

Copilot uses AI. Check for mistakes.
address sender = LibMeta.msgSender();
uint256 ghstBalance = IERC20(s.ghstContract).balanceOf(sender);
require(ghstBalance >= _priceInWei, "ERC721BuyOrder: Not enough GHST!");

// Aavegotchi-specific validation
if (_erc721TokenAddress == address(this)) {
AavegotchiInfo memory aavegotchiInfo = LibAavegotchi.getAavegotchi(_erc721TokenId);
uint256 category = aavegotchiInfo.status;
require(category == _category, "ERC721BuyOrder: Category mismatch");
require(category != LibAavegotchi.STATUS_VRF_PENDING, "ERC721BuyOrder: Cannot buy a portal that is pending VRF");

if (category == LibAavegotchi.STATUS_AAVEGOTCHI) {
require(_validationOptions.length == 3, "ERC721BuyOrder: Not enough validation options for aavegotchi");
}
}

require(sender != IERC721(_erc721TokenAddress).ownerOf(_erc721TokenId), "ERC721BuyOrder: Owner can't be buyer");

uint256 oldBuyOrderId = s.buyerToBuyOrderId[_erc721TokenAddress][_erc721TokenId][sender];
if (oldBuyOrderId != 0) {
ERC721BuyOrder memory erc721BuyOrder = s.erc721BuyOrders[oldBuyOrderId];
require(erc721BuyOrder.timeCreated != 0, "ERC721BuyOrder: ERC721 buyOrder does not exist");
require(erc721BuyOrder.cancelled == false && erc721BuyOrder.timePurchased == 0, "ERC721BuyOrder: Already processed");
if ((erc721BuyOrder.duration == 0) || (erc721BuyOrder.timeCreated + erc721BuyOrder.duration >= block.timestamp)) {
LibBuyOrder.cancelERC721BuyOrder(oldBuyOrderId);
emit ERC721BuyOrderCanceled(oldBuyOrderId, block.timestamp);
}
}
uint256 totalCost = LibBuyOrder.validateERC721Params(_erc721TokenAddress, _erc721TokenId, _category, _priceInWei, _validationOptions);

// Transfer GHST
LibERC20.transferFrom(s.ghstContract, sender, address(this), _priceInWei);
LibERC20.transferFrom(s.ghstContract, sender, address(this), totalCost);

// Place new buy order
s.nextERC721BuyOrderId++;
uint256 buyOrderId = s.nextERC721BuyOrderId;

s.buyerToBuyOrderId[_erc721TokenAddress][_erc721TokenId][sender] = buyOrderId;

bytes32 _validationHash = LibBuyOrder.generateValidationHash(_erc721TokenAddress, _erc721TokenId, _validationOptions);
s.erc721BuyOrders[buyOrderId] = ERC721BuyOrder({
buyOrderId: buyOrderId,
buyer: sender,
erc721TokenAddress: _erc721TokenAddress,
erc721TokenId: _erc721TokenId,
priceInWei: _priceInWei,
validationHash: _validationHash,
timeCreated: block.timestamp,
timePurchased: 0,
duration: _duration,
cancelled: false,
validationOptions: _validationOptions
});
emit ERC721BuyOrderAdded(
buyOrderId,
sender,
_erc721TokenAddress,
_erc721TokenId,
_category,
_priceInWei,
_duration,
_validationHash,
block.timestamp
);
LibBuyOrder._placeERC721BuyOrder(_erc721TokenAddress, _erc721TokenId, _category, _priceInWei, _duration, _validationOptions);
}

function cancelERC721BuyOrder(uint256 _buyOrderId) external whenNotPaused {
Expand All @@ -174,7 +110,7 @@ contract ERC721BuyOrderFacet is Modifiers {
}

LibBuyOrder.cancelERC721BuyOrder(_buyOrderId);
emit ERC721BuyOrderCanceled(_buyOrderId, block.timestamp);
emit LibBuyOrder.ERC721BuyOrderCanceled(_buyOrderId, block.timestamp);
}

function executeERC721BuyOrder(
Expand Down
Loading
Loading