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 ERC1155
  • Loading branch information
capedcrusader21 committed Sep 11, 2024
1 parent e96dac6 commit e1a4a27
Show file tree
Hide file tree
Showing 7 changed files with 631 additions and 831 deletions.
2 changes: 0 additions & 2 deletions packages/marketplace/contracts/ExchangeCore.sol
Original file line number Diff line number Diff line change
Expand Up @@ -173,8 +173,6 @@ abstract contract ExchangeCore is Initializable, ITransferManager {
orderRight.makeAsset.assetType
);

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

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

doTransfers(
Expand Down
4 changes: 0 additions & 4 deletions packages/marketplace/contracts/OrderValidator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,6 @@ 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);
}
} else makeToken = LibAsset.decodeAddress(asset.assetType);
if (asset.assetType.assetClass == LibAsset.AssetClass.ERC20) {
_verifyWhitelistsRoles(makeToken);
Expand Down
37 changes: 23 additions & 14 deletions packages/marketplace/contracts/TransferManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -111,10 +111,20 @@ abstract contract TransferManager is Initializable, ITransferManager {
nftSide = left;
}

LibAsset.verifyPriceDistribution(nftSide.asset, nftSide.asset.value, paymentSide.asset.value);

(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 +277,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 +417,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 Expand Up @@ -490,7 +499,7 @@ abstract contract TransferManager is Initializable, ITransferManager {
/// @param y The bottom left y coordinate of the quad
/// @return the tokenId of the quad
/// @dev this method is gas optimized, must be called with verified x,y and size, after a call to _isValidQuad
function idInPath(uint256 i, uint256 size, uint256 x, uint256 y) internal view returns (uint256) {
function idInPath(uint256 i, uint256 size, uint256 x, uint256 y) internal pure returns (uint256) {
unchecked {
return (x + (i % size)) + (y + (i / size)) * GRID_SIZE;
}
Expand Down
25 changes: 8 additions & 17 deletions packages/marketplace/contracts/libraries/LibAsset.sol
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,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 +59,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 +67,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 +151,18 @@ 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 nftSideValue The value on nft side order.
/// @param paymentSideValue The value on payment side order.
function verifyPriceDistribution(
Asset memory leftAsset,
uint256 nftSideValue,
uint256 paymentSideValue
) 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 +183,7 @@ library LibAsset {
collectiveBundlePrice += priceDistribution.quadPrices[i];
}

require(bundlePrice == collectiveBundlePrice, "Bundle price mismatch");
require(paymentSideValue == collectiveBundlePrice * nftSideValue, "Bundle price mismatch");
}
}

Expand Down
8 changes: 3 additions & 5 deletions packages/marketplace/docs/Exchange.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
The [Exchange contract](../contracts/Exchange.sol) is the entrypoint and main
contract to the marketplace protocol. It safely offers a decentralized way to
exchange tokens of any nature (ERC20, ERC1155, ERC721) using signed orders.It
also supports exchanging bundles of assets, which can include multiple ERC20,
ERC1155, ERC721, and Quads.
also supports exchanging bundles of assets, which can include multiple ERC1155,
ERC721, and Quads.

## Concepts

Expand Down Expand Up @@ -39,9 +39,7 @@ Alice wants to sell a bundle of assets:
1 LAND (ERC721) with token id 1000
- Price: 1200 MATIC
10 ASSET (ERC1155) with token id 2000
- Price: 500 MATIC
50 SAND (ERC20)
- Price: 300 MATIC (6 MATIC per SAND)
- Price: 700 MATIC
against 2000 MATIC (ERC20).
```

Expand Down
Loading

1 comment on commit e1a4a27

@github-actions
Copy link

Choose a reason for hiding this comment

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

Coverage for this commit

98.06%

Coverage Report
FileStmtsBranchesFuncsLinesUncovered Lines
packages/marketplace/contracts
   Exchange.sol94.52%93.33%94.44%96%126, 194, 72
   ExchangeCore.sol98.84%96.67%100%100%85
   OrderValidator.sol96.49%92.31%100%100%105, 36
   RoyaltiesRegistry.sol96.32%88.89%100%98.78%194, 216–217, 263, 65
   TransferManager.sol95.28%86.11%100%99.30%163, 214, 224, 274, 418, 423, 434, 446–447, 458, 93
   Whitelist.sol75.81%60%85.71%82.14%104, 108–109, 122, 125, 141–142, 54, 66, 66–67, 71, 76
packages/marketplace/contracts/interfaces
   IOrderValidator.sol100%100%100%100%
   IRoyaltiesProvider.sol100%100%100%100%
   ITransferManager.sol100%100%100%100%
   IWhitelist.sol100%100%100%100%
packages/marketplace/contracts/libraries
   LibAsset.sol100%100%100%100%
   LibMath.sol100%100%100%100%
   LibOrder.sol100%100%100%100%

Please sign in to comment.