Skip to content

Commit

Permalink
feat: removed bundledERC20 and added logic to exchange multiple bundl…
Browse files Browse the repository at this point in the history
…es with ERC1155s
  • Loading branch information
capedcrusader21 committed Sep 11, 2024
1 parent e96dac6 commit 7cdc4e7
Show file tree
Hide file tree
Showing 6 changed files with 624 additions and 825 deletions.
4 changes: 2 additions & 2 deletions packages/marketplace/contracts/ExchangeCore.sol
Original file line number Diff line number Diff line change
Expand Up @@ -173,10 +173,10 @@ abstract contract ExchangeCore is Initializable, ITransferManager {
orderRight.makeAsset.assetType
);

LibAsset.verifyPriceDistribution(orderLeft.takeAsset, orderRight.takeAsset);

LibOrder.FillResult memory newFill = _parseOrdersSetFillEmitMatch(sender, orderLeft, orderRight);

LibAsset.verifyPriceDistribution(orderLeft.takeAsset, newFill);

doTransfers(
ITransferManager.DealSide(LibAsset.Asset(makeMatch, newFill.leftValue), orderLeft.maker),
ITransferManager.DealSide(LibAsset.Asset(takeMatch, newFill.rightValue), orderRight.maker),
Expand Down
5 changes: 1 addition & 4 deletions packages/marketplace/contracts/OrderValidator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,7 @@ contract OrderValidator is IOrderValidator, Initializable, EIP712Upgradeable, ER
address makeToken;
if (asset.assetType.assetClass == LibAsset.AssetClass.BUNDLE) {
LibAsset.Bundle memory bundle = LibAsset.decodeBundle(asset.assetType);
for (uint256 i; i < bundle.bundledERC20.length; i++) {
makeToken = bundle.bundledERC20[i].erc20Address;
_verifyWhitelistsRoles(makeToken);
}
// TODO add token verification in M-02 audit fix
} else makeToken = LibAsset.decodeAddress(asset.assetType);
if (asset.assetType.assetClass == LibAsset.AssetClass.ERC20) {
_verifyWhitelistsRoles(makeToken);
Expand Down
33 changes: 20 additions & 13 deletions packages/marketplace/contracts/TransferManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,15 @@ abstract contract TransferManager is Initializable, ITransferManager {
(address paymentSideRecipient, address nftSideRecipient) = _getRecipients(paymentSide, nftSide);

// Transfer NFT or left side if FeeSide.NONE
_transfer(nftSide.asset, nftSide.account, paymentSideRecipient);
// NFT transfer when exchanging more than one bundle of ERC1155s
if (nftSide.asset.assetType.assetClass == LibAsset.AssetClass.BUNDLE && nftSide.asset.value > 1) {
for (uint256 i = 0; i < nftSide.asset.value; i++) {
_transfer(nftSide.asset, nftSide.account, paymentSideRecipient);
}
} else {
_transfer(nftSide.asset, nftSide.account, paymentSideRecipient);
}

// Transfer ERC20 or right side if FeeSide.NONE
if (feeSide == LibAsset.FeeSide.NONE || _mustSkipFees(nftSide.account)) {
_transfer(paymentSide.asset, paymentSide.account, nftSideRecipient);
Expand Down Expand Up @@ -267,13 +275,17 @@ abstract contract TransferManager is Initializable, ITransferManager {
token,
bundle.bundledERC1155[i].ids[j]
);
remainder = _applyRoyalties(
remainder,
paymentSide,
bundle.priceDistribution.erc1155Prices[i][j],
royalties,
nftSideRecipient
);

// royalty transfer when exchanging one or more than one bundle of ERC1155s
for (uint256 k; k < nftSide.asset.value; k++) {
remainder = _applyRoyalties(
remainder,
paymentSide,
bundle.priceDistribution.erc1155Prices[i][j],
royalties,
nftSideRecipient
);
}
}
}

Expand Down Expand Up @@ -403,15 +415,10 @@ abstract contract TransferManager is Initializable, ITransferManager {
_transferERC1155(token, from, to, tokenId, asset.value);
} else if (asset.assetType.assetClass == LibAsset.AssetClass.BUNDLE) {
LibAsset.Bundle memory bundle = LibAsset.decodeBundle(asset.assetType);
uint256 erc20Length = bundle.bundledERC20.length;
uint256 erc721Length = bundle.bundledERC721.length;
uint256 erc1155Length = bundle.bundledERC1155.length;
uint256 quadsLength = bundle.quads.xs.length;
if (erc721Length > 0 || quadsLength > 0) require(asset.value == 1, "bundle value error");
for (uint256 i; i < erc20Length; i++) {
address token = bundle.bundledERC20[i].erc20Address;
_transferERC20(token, from, to, bundle.bundledERC20[i].value);
}
for (uint256 i; i < erc721Length; i++) {
address token = bundle.bundledERC721[i].erc721Address;
uint256 idLength = bundle.bundledERC721[i].ids.length;
Expand Down
21 changes: 4 additions & 17 deletions packages/marketplace/contracts/libraries/LibAsset.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: MIT

pragma solidity 0.8.23;
import {LibOrder} from "./LibOrder.sol";

/// @author The Sandbox
/// @title LibAsset: A library for handling different types of Ethereum assets.
Expand Down Expand Up @@ -36,12 +37,6 @@ library LibAsset {
uint256 value; // The amount or value of the asset.
}

/// @dev Represents a group (i.e. bundle) of ERC20 asset.
struct BundledERC20 {
address erc20Address;
uint256 value;
}

/// @dev Represents a group (i.e. bundle) of ERC721 assets.
struct BundledERC721 {
address erc721Address;
Expand All @@ -65,7 +60,6 @@ library LibAsset {

/// @dev Represents a group (i.e. bundle) of assets with its types and values.
struct Bundle {
BundledERC20[] bundledERC20;
BundledERC721[] bundledERC721;
BundledERC1155[] bundledERC1155;
Quads quads;
Expand All @@ -74,7 +68,6 @@ library LibAsset {

/// @dev Represents the price of each asset in a bundle.
struct PriceDistribution {
uint256[] erc20Prices;
uint256[][] erc721Prices;
uint256[][] erc1155Prices;
uint256[] quadPrices;
Expand Down Expand Up @@ -159,19 +152,13 @@ library LibAsset {

/// @dev function to verify if the order is a bundle and validate the bundle price
/// @param leftAsset The left asset.
/// @param rightAsset The right asset.
function verifyPriceDistribution(Asset memory leftAsset, Asset memory rightAsset) internal pure {
/// @param fill The fill.
function verifyPriceDistribution(Asset memory leftAsset, LibOrder.FillResult memory fill) internal pure {
if (leftAsset.assetType.assetClass == AssetClass.BUNDLE) {
uint256 bundlePrice = rightAsset.value; // bundle price provided by seller
Bundle memory bundle = LibAsset.decodeBundle(leftAsset.assetType);
PriceDistribution memory priceDistribution = bundle.priceDistribution;
uint256 collectiveBundlePrice = 0;

// total price of all bundled ERC20 assets
for (uint256 i = 0; i < priceDistribution.erc20Prices.length; i++) {
collectiveBundlePrice += priceDistribution.erc20Prices[i];
}

// total price of all bundled ERC721 assets
for (uint256 i = 0; i < priceDistribution.erc721Prices.length; i++) {
for (uint256 j = 0; j < priceDistribution.erc721Prices[i].length; j++)
Expand All @@ -192,7 +179,7 @@ library LibAsset {
collectiveBundlePrice += priceDistribution.quadPrices[i];
}

require(bundlePrice == collectiveBundlePrice, "Bundle price mismatch");
require(fill.rightValue == collectiveBundlePrice * fill.leftValue, "Bundle price mismatch");
}
}

Expand Down
Loading

0 comments on commit 7cdc4e7

Please sign in to comment.