Skip to content

Commit

Permalink
Merge pull request #126 from ourzora/offers
Browse files Browse the repository at this point in the history
[feat] Offers v1.0
  • Loading branch information
tbtstl authored Feb 9, 2022
2 parents b47a6f2 + 6153434 commit 43ffff7
Show file tree
Hide file tree
Showing 14 changed files with 1,166 additions and 5 deletions.
3 changes: 2 additions & 1 deletion addresses/1.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@
"ERC20TransferHelper": "0xCCA379FDF4Beda63c4bB0e2A3179Ae62c8716794",
"ERC721TransferHelper": "0x909e9efE4D87d1a6018C2065aE642b6D0447bc91",
"AsksV1": "0xCe6cEf2A9028e1C3B21647ae3B4251038109f42a",
"AsksV1_1": "0x6170B3C3A54C3d8c854934cBC314eD479b2B29A3"
"AsksV1_1": "0x6170B3C3A54C3d8c854934cBC314eD479b2B29A3",
"OffersV1": "0x76744367ae5a056381868f716bdf0b13ae1aeaa3"
}
5 changes: 3 additions & 2 deletions addresses/4.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@
"ERC20TransferHelper": "0x408AbC192a5e9696085EBaFC7C5A88e19e66241b",
"ERC721TransferHelper": "0x029AA5a949C9C90916729D50537062cb73b5Ac92",
"AsksV1": "0x850356153abBdFA1B473e2D86F2DF11a85B408B8",
"AsksV1_1": "0xA98D3729265C88c5b3f861a0c501622750fF4806"
}
"AsksV1_1": "0xA98D3729265C88c5b3f861a0c501622750fF4806",
"OffersV1": "0x1240ef9f9c56ee981d10cffc6ba5807b6c7fecaa"
}
438 changes: 438 additions & 0 deletions contracts/modules/Offers/V1/OffersV1.sol

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions contracts/test/ZoraModuleManager.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ contract ZoraModuleManagerTest is DSTest {
module = batchModules[0];
}

/// ------------ APPROVE MODULE ------------
/// ------------ APPROVE MODULE ------------ ///

function test_SetApproval() public {
registrar.registerModule(module);
Expand All @@ -62,7 +62,7 @@ contract ZoraModuleManagerTest is DSTest {
bob.setApprovalForModule(module, true);
}

/// ------------ APPROVE MODULE BATCH ------------
/// ------------ APPROVE MODULE BATCH ------------ ///

function test_SetBatchApproval() public {
for (uint256 i = 0; i < 3; i++) {
Expand Down
166 changes: 166 additions & 0 deletions contracts/test/modules/Offers/V1/Offers.integration.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.10;

import {DSTest} from "ds-test/test.sol";

import {OffersV1} from "../../../../modules/Offers/V1/OffersV1.sol";
import {Zorb} from "../../../utils/users/Zorb.sol";
import {ZoraRegistrar} from "../../../utils/users/ZoraRegistrar.sol";
import {ZoraModuleManager} from "../../../../ZoraModuleManager.sol";
import {ZoraProtocolFeeSettings} from "../../../../auxiliary/ZoraProtocolFeeSettings/ZoraProtocolFeeSettings.sol";
import {ERC20TransferHelper} from "../../../../transferHelpers/ERC20TransferHelper.sol";
import {ERC721TransferHelper} from "../../../../transferHelpers/ERC721TransferHelper.sol";
import {RoyaltyEngine} from "../../../utils/modules/RoyaltyEngine.sol";

import {TestERC721} from "../../../utils/tokens/TestERC721.sol";
import {WETH} from "../../../utils/tokens/WETH.sol";
import {VM} from "../../../utils/VM.sol";

/// @title OffersV1IntegrationTest
/// @notice Integration Tests for Offers v1.0
contract OffersV1IntegrationTest is DSTest {
VM internal vm;

ZoraRegistrar internal registrar;
ZoraProtocolFeeSettings internal ZPFS;
ZoraModuleManager internal ZMM;
ERC20TransferHelper internal erc20TransferHelper;
ERC721TransferHelper internal erc721TransferHelper;
RoyaltyEngine internal royaltyEngine;

OffersV1 internal offers;
TestERC721 internal token;
WETH internal weth;

Zorb internal seller;
Zorb internal buyer;
Zorb internal finder;
Zorb internal royaltyRecipient;

function setUp() public {
// Cheatcodes
vm = VM(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D);

// Deploy V3
registrar = new ZoraRegistrar();
ZPFS = new ZoraProtocolFeeSettings();
ZMM = new ZoraModuleManager(address(registrar), address(ZPFS));
erc20TransferHelper = new ERC20TransferHelper(address(ZMM));
erc721TransferHelper = new ERC721TransferHelper(address(ZMM));

// Init V3
registrar.init(ZMM);
ZPFS.init(address(ZMM), address(0));

// Create users
seller = new Zorb(address(ZMM));
buyer = new Zorb(address(ZMM));
finder = new Zorb(address(ZMM));
royaltyRecipient = new Zorb(address(ZMM));

// Deploy mocks
royaltyEngine = new RoyaltyEngine(address(royaltyRecipient));
token = new TestERC721();
weth = new WETH();

// Deploy Offers v1.0
offers = new OffersV1(address(erc20TransferHelper), address(erc721TransferHelper), address(royaltyEngine), address(ZPFS), address(weth));
registrar.registerModule(address(offers));

// Set seller balance
vm.deal(address(seller), 100 ether);

// Mint buyer token
token.mint(address(buyer), 0);

// Seller swap 50 ETH <> 50 WETH
vm.prank(address(seller));
weth.deposit{value: 50 ether}();

// Users approve Offers module
seller.setApprovalForModule(address(offers), true);
buyer.setApprovalForModule(address(offers), true);

// Seller approve ERC20TransferHelper
vm.prank(address(seller));
weth.approve(address(erc20TransferHelper), 50 ether);

// Buyer approve ERC721TransferHelper
vm.prank(address(buyer));
token.setApprovalForAll(address(erc721TransferHelper), true);
}

/// ------------ ETH Offer ------------ ///

function runETH() public {
vm.prank(address(seller));
uint256 id = offers.createOffer{value: 1 ether}(address(token), 0, address(0), 1 ether, 1000);

vm.prank(address(buyer));
offers.fillOffer(address(token), 0, id, address(0), 1 ether, address(finder));
}

function test_ETHIntegration() public {
uint256 beforeSellerBalance = address(seller).balance;
uint256 beforeBuyerBalance = address(buyer).balance;
uint256 beforeRoyaltyRecipientBalance = address(royaltyRecipient).balance;
uint256 beforeFinderBalance = address(finder).balance;
address beforeTokenOwner = token.ownerOf(0);

runETH();

uint256 afterSellerBalance = address(seller).balance;
uint256 afterBuyerBalance = address(buyer).balance;
uint256 afterRoyaltyRecipientBalance = address(royaltyRecipient).balance;
uint256 afterFinderBalance = address(finder).balance;
address afterTokenOwner = token.ownerOf(0);

// 1 ETH withdrawn from seller
require((beforeSellerBalance - afterSellerBalance) == 1 ether);
// 0.05 ETH creator royalty
require((afterRoyaltyRecipientBalance - beforeRoyaltyRecipientBalance) == 0.05 ether);
// 1000 bps finders fee (Remaining 0.95 ETH * 10% finders fee = 0.095 ETH)
require((afterFinderBalance - beforeFinderBalance) == 0.095 ether);
// Remaining 0.855 ETH paid to buyer
require((afterBuyerBalance - beforeBuyerBalance) == 0.855 ether);
// NFT transferred to seller
require((beforeTokenOwner == address(buyer)) && afterTokenOwner == address(seller));
}

/// ------------ ERC-20 Offer ------------ ///

function runERC20() public {
vm.prank(address(seller));
uint256 id = offers.createOffer(address(token), 0, address(weth), 1 ether, 1000);

vm.prank(address(buyer));
offers.fillOffer(address(token), 0, id, address(weth), 1 ether, address(finder));
}

function test_ERC20Integration() public {
uint256 beforeSellerBalance = weth.balanceOf(address(seller));
uint256 beforeBuyerBalance = weth.balanceOf(address(buyer));
uint256 beforeRoyaltyRecipientBalance = weth.balanceOf(address(royaltyRecipient));
uint256 beforeFinderBalance = weth.balanceOf(address(finder));
address beforeTokenOwner = token.ownerOf(0);

runERC20();

uint256 afterSellerBalance = weth.balanceOf(address(seller));
uint256 afterBuyerBalance = weth.balanceOf(address(buyer));
uint256 afterRoyaltyRecipientBalance = weth.balanceOf(address(royaltyRecipient));
uint256 afterFinderBalance = weth.balanceOf(address(finder));
address afterTokenOwner = token.ownerOf(0);

// 1 WETH withdrawn from seller
require((beforeSellerBalance - afterSellerBalance) == 1 ether);
// 0.05 WETH creator royalty
require((afterRoyaltyRecipientBalance - beforeRoyaltyRecipientBalance) == 0.05 ether);
// 0.095 WETH finders fee (0.95 WETH * 10% finders fee)
require((afterFinderBalance - beforeFinderBalance) == 0.095 ether);
// Remaining 0.855 WETH paid to buyer
require((afterBuyerBalance - beforeBuyerBalance) == 0.855 ether);
// NFT transferred to seller
require((beforeTokenOwner == address(buyer)) && afterTokenOwner == address(seller));
}
}
Loading

0 comments on commit 43ffff7

Please sign in to comment.