Skip to content
This repository has been archived by the owner on Dec 23, 2024. It is now read-only.

Commit

Permalink
Merge pull request #126 from ourzora/offers
Browse files Browse the repository at this point in the history
[feat] Offers v1.0
tbtstl authored Feb 9, 2022
2 parents b47a6f2 + 6153434 commit 43ffff7
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
@@ -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
@@ -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
@@ -48,7 +48,7 @@ contract ZoraModuleManagerTest is DSTest {
module = batchModules[0];
}

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

function test_SetApproval() public {
registrar.registerModule(module);
@@ -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++) {
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));
}
}
325 changes: 325 additions & 0 deletions contracts/test/modules/Offers/V1/Offers.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,325 @@
// 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 OffersV1Test
/// @notice Unit Tests for Offers v1.0
contract OffersV1Test 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 maker;
Zorb internal taker;
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
maker = new Zorb(address(ZMM));
taker = 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 maker balance
vm.deal(address(maker), 100 ether);

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

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

// Users approve Offers module
maker.setApprovalForModule(address(offers), true);
taker.setApprovalForModule(address(offers), true);

// Maker approve ERC20TransferHelper
vm.prank(address(maker));
weth.approve(address(erc20TransferHelper), 50 ether);

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

/// ------------ CREATE NFT OFFER ------------ ///

function testGas_CreateOffer() public {
offers.createOffer{value: 1 ether}(address(token), 0, address(0), 1 ether, 1000);
}

function test_CreateOffer() public {
vm.prank(address(maker));
offers.createOffer{value: 1 ether}(address(token), 0, address(0), 1 ether, 1000);

(address offeror, , , ) = offers.offers(address(token), 0, 1);

require(offeror == address(maker));
}

function testFail_CannotCreateOfferWithoutAttachingFunds() public {
vm.prank(address(maker));
offers.createOffer(address(token), 0, address(0), 1 ether, 1000);
}

function testFail_CannotCreateOfferWithInvalidFindersFeeBps() public {
vm.prank(address(maker));
offers.createOffer(address(token), 0, address(0), 1 ether, 10001);
}

/// ------------ SET NFT OFFER ------------ ///

function test_IncreaseETHOffer() public {
vm.startPrank(address(maker));

offers.createOffer{value: 1 ether}(address(token), 0, address(0), 1 ether, 1000);

vm.warp(1 hours);

offers.setOfferAmount{value: 1 ether}(address(token), 0, 1, address(0), 2 ether);

vm.stopPrank();

(, , , uint256 amount) = offers.offers(address(token), 0, 1);

require(amount == 2 ether);
require(address(offers).balance == 2 ether);
}

function test_DecreaseETHOffer() public {
vm.startPrank(address(maker));

offers.createOffer{value: 1 ether}(address(token), 0, address(0), 1 ether, 1000);

vm.warp(1 hours);

offers.setOfferAmount(address(token), 0, 1, address(0), 0.5 ether);

vm.stopPrank();

(, , , uint256 amount) = offers.offers(address(token), 0, 1);

require(amount == 0.5 ether);
require(address(offers).balance == 0.5 ether);
}

function test_IncreaseETHOfferWithERC20() public {
vm.startPrank(address(maker));

offers.createOffer{value: 1 ether}(address(token), 0, address(0), 1 ether, 1000);

vm.warp(1 hours);

offers.setOfferAmount(address(token), 0, 1, address(weth), 2 ether);

vm.stopPrank();

(, , , uint256 amount) = offers.offers(address(token), 0, 1);

require(amount == 2 ether);
require(weth.balanceOf(address(offers)) == 2 ether);
require(address(offers).balance == 0 ether);
}

function test_DecreaseETHOfferWithERC20() public {
vm.startPrank(address(maker));

offers.createOffer{value: 1 ether}(address(token), 0, address(0), 1 ether, 1000);

vm.warp(1 hours);

offers.setOfferAmount(address(token), 0, 1, address(weth), 0.5 ether);

vm.stopPrank();

(, , , uint256 amount) = offers.offers(address(token), 0, 1);

require(amount == 0.5 ether);
require(weth.balanceOf(address(offers)) == 0.5 ether);
require(address(offers).balance == 0 ether);
}

function testRevert_OnlySellerCanUpdateOffer() public {
vm.prank(address(maker));
offers.createOffer{value: 1 ether}(address(token), 0, address(0), 1 ether, 1000);

vm.expectRevert("setOfferAmount must be maker");
offers.setOfferAmount(address(token), 0, 1, address(0), 0.5 ether);
}

function testRevert_CannotIncreaseOfferWithoutAttachingFunds() public {
vm.startPrank(address(maker));

offers.createOffer{value: 1 ether}(address(token), 0, address(0), 1 ether, 1000);
vm.expectRevert("_handleIncomingTransfer msg value less than expected amount");
offers.setOfferAmount(address(token), 0, 1, address(0), 2 ether);

vm.stopPrank();
}

function testRevert_CannotUpdateOfferWithPreviousAmount() public {
vm.startPrank(address(maker));

offers.createOffer{value: 1 ether}(address(token), 0, address(0), 1 ether, 1000);

vm.warp(1 hours);

vm.expectRevert("setOfferAmount invalid _amount");

offers.setOfferAmount{value: 1 ether}(address(token), 0, 1, address(0), 1 ether);

vm.stopPrank();
}

function testRevert_CannotUpdateInactiveOffer() public {
vm.prank(address(maker));
offers.createOffer{value: 1 ether}(address(token), 0, address(0), 1 ether, 1000);

vm.prank(address(taker));
offers.fillOffer(address(token), 0, 1, address(0), 1 ether, address(finder));

vm.prank(address(maker));
vm.expectRevert("setOfferAmount must be maker");
offers.setOfferAmount(address(token), 0, 1, address(0), 0.5 ether);
}

/// ------------ CANCEL NFT OFFER ------------ ///

function test_CancelNFTOffer() public {
vm.startPrank(address(maker));

offers.createOffer{value: 1 ether}(address(token), 0, address(0), 1 ether, 1000);

(, , , uint256 beforeAmount) = offers.offers(address(token), 0, 1);
require(beforeAmount == 1 ether);

offers.cancelOffer(address(token), 0, 1);

(, , , uint256 afterAmount) = offers.offers(address(token), 0, 1);
require(afterAmount == 0);

vm.stopPrank();
}

function testRevert_CannotCancelInactiveOffer() public {
vm.prank(address(maker));
offers.createOffer{value: 1 ether}(address(token), 0, address(0), 1 ether, 1000);

vm.prank(address(taker));
offers.fillOffer(address(token), 0, 1, address(0), 1 ether, address(finder));

vm.prank(address(maker));
vm.expectRevert("cancelOffer must be maker");
offers.cancelOffer(address(token), 0, 1);
}

function testRevert_OnlySellerCanCancelOffer() public {
vm.prank(address(maker));
offers.createOffer{value: 1 ether}(address(token), 0, address(0), 1 ether, 1000);

vm.expectRevert("cancelOffer must be maker");
offers.cancelOffer(address(token), 0, 1);
}

/// ------------ FILL NFT OFFER ------------ ///

function test_FillNFTOffer() public {
vm.prank(address(maker));
offers.createOffer{value: 1 ether}(address(token), 0, address(0), 1 ether, 1000);

address beforeTokenOwner = token.ownerOf(0);

vm.prank(address(taker));
offers.fillOffer(address(token), 0, 1, address(0), 1 ether, address(finder));

address afterTokenOwner = token.ownerOf(0);

require(beforeTokenOwner == address(taker) && afterTokenOwner == address(maker));
}

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

vm.expectRevert("fillOffer must be token owner");
offers.fillOffer(address(token), 0, id, address(0), 1 ether, address(finder));
}

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

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

vm.prank(address(taker));
vm.expectRevert("fillOffer must be active offer");
offers.fillOffer(address(token), 0, id, address(0), 1 ether, address(finder));
}

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

vm.prank(address(taker));
vm.expectRevert("fillOffer _currency & _amount must match offer");
offers.fillOffer(address(token), 0, id, address(weth), 1 ether, address(finder));
}

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

vm.prank(address(taker));
vm.expectRevert("fillOffer _currency & _amount must match offer");
offers.fillOffer(address(token), 0, id, address(0), 0.5 ether, address(finder));
}
}
29 changes: 29 additions & 0 deletions uml/OffersV1/cancelOffer.atxt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
,-.
`-'
/|\
| ,--------. ,-------------------.
/ \ |OffersV1| |ERC20TransferHelper|
Caller `---+----' `---------+---------'
| cancelOffer() | |
| -----------------> |
| | |
| | transferFrom() |
| | ------------------------>
| | |
| | |----.
| | | | refund tokens from escrow
| | |<---'
| | |
| |----.
| | | emit OfferCanceled()
| |<---'
| | |
| |----. |
| | | delete offer |
| |<---' |
Caller ,---+----. ,---------+---------.
,-. |OffersV1| |ERC20TransferHelper|
`-' `--------' `-------------------'
/|\
|
/ \
13 changes: 13 additions & 0 deletions uml/OffersV1/cancelOffer.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
@startuml
actor Caller
participant OffersV1
participant ERC20TransferHelper

Caller -> OffersV1 : cancelOffer()
OffersV1 -> ERC20TransferHelper : transferFrom()
ERC20TransferHelper -> ERC20TransferHelper : refund tokens from escrow
OffersV1 -> OffersV1 : emit OfferCanceled()
OffersV1 -> OffersV1 : delete offer

@enduml

40 changes: 40 additions & 0 deletions uml/OffersV1/createOffer.atxt
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
,-.
`-'
/|\
| ,--------. ,-------------------.
/ \ |OffersV1| |ERC20TransferHelper|
Caller `---+----' `---------+---------'
| createOffer() | |
| -----------------> |
| | |
| | transferFrom() |
| | ----------------------------->
| | |
| | |----.
| | | | transfer tokens into escrow
| | |<---'
| | |
| |----. |
| | | offer count ++ |
| |<---' |
| | |
| |----. |
| | | create offer |
| |<---' |
| | |
| |----.
| | | offersFor[NFT].append(id)
| |<---'
| | |
| |----. |
| | | emit OfferCreated() |
| |<---' |
| | |
| id | |
| <----------------- |
Caller ,---+----. ,---------+---------.
,-. |OffersV1| |ERC20TransferHelper|
`-' `--------' `-------------------'
/|\
|
/ \
16 changes: 16 additions & 0 deletions uml/OffersV1/createOffer.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
@startuml
actor Caller
participant OffersV1
participant ERC20TransferHelper

Caller -> OffersV1 : createOffer()
OffersV1 -> ERC20TransferHelper : transferFrom()
ERC20TransferHelper -> ERC20TransferHelper : transfer tokens into escrow
OffersV1 -> OffersV1 : offer count ++
OffersV1 -> OffersV1 : create offer
OffersV1 -> OffersV1 : offersFor[NFT].append(id)
OffersV1 -> OffersV1 : emit OfferCreated()
OffersV1 -> Caller :id

@enduml

51 changes: 51 additions & 0 deletions uml/OffersV1/fillOffer.atxt
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
,-.
`-'
/|\
| ,--------. ,--------------------.
/ \ |OffersV1| |ERC721TransferHelper|
Caller `---+----' `---------+----------'
| fillOffer() | |
| -----------------> |
| | |
| |----. |
| | | validate token owner |
| |<---' |
| | |
| |----. |
| | | handle royalty payouts |
| |<---' |
| | |
| | |
| __________________________________________________
| ! ALT / finders fee configured for this offer? !
| !_____/ | | !
| ! |----. | !
| ! | | handle finders fee payout| !
| ! |<---' | !
| !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!
| !~[noop]~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!
| | |
| | transferFrom() |
| | ------------------------------>
| | |
| | |----.
| | | | transfer NFT from taker to maker
| | |<---'
| | |
| |----. |
| | | emit ExchangeExecuted() |
| |<---' |
| | |
| |----. |
| | | emit OfferFilled() |
| |<---' |
| | |
| |----.
| | | delete offer from contract
| |<---'
Caller ,---+----. ,---------+----------.
,-. |OffersV1| |ERC721TransferHelper|
`-' `--------' `--------------------'
/|\
|
/ \
27 changes: 27 additions & 0 deletions uml/OffersV1/fillOffer.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
@startuml
actor Caller
participant OffersV1
participant ERC721TransferHelper

Caller -> OffersV1 : fillOffer()

OffersV1 -> OffersV1 : validate token owner

OffersV1 -> OffersV1 : handle royalty payouts

alt finders fee configured for this offer?

OffersV1 -> OffersV1 : handle finders fee payout

else noop

end

OffersV1 -> ERC721TransferHelper : transferFrom()
ERC721TransferHelper -> ERC721TransferHelper : transfer NFT from taker to maker

OffersV1 -> OffersV1 : emit ExchangeExecuted()
OffersV1 -> OffersV1 : emit OfferFilled()
OffersV1 -> OffersV1 : delete offer from contract

@enduml
33 changes: 33 additions & 0 deletions uml/OffersV1/setOfferAmount.atxt
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
,-.
`-'
/|\
| ,--------. ,-------------------.
/ \ |OffersV1| |ERC20TransferHelper|
Caller `---+----' `---------+---------'
| setOfferAmount() | |
| -----------------> |
| | |
| | |
| _______________________________________________________________________
| ! ALT / same token? | !
| !_____/ | | !
| ! | retrieve increase / refund decrease| !
| ! | -----------------------------------> !
| !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!
| ! [different token] | !
| ! | refund previous offer | !
| ! | -----------------------------------> !
| ! | | !
| ! | retrieve new offer | !
| ! | -----------------------------------> !
| !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!
| | |
| |----. |
| | | emit OfferUpdated() |
| |<---' |
Caller ,---+----. ,---------+---------.
,-. |OffersV1| |ERC20TransferHelper|
`-' `--------' `-------------------'
/|\
|
/ \
21 changes: 21 additions & 0 deletions uml/OffersV1/setOfferAmount.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
@startuml
actor Caller
participant OffersV1
participant ERC20TransferHelper

Caller -> OffersV1 : setOfferAmount()

alt same token?

OffersV1 -> ERC20TransferHelper : retrieve increase / refund decrease

else different token

OffersV1 -> ERC20TransferHelper : refund previous offer

OffersV1 -> ERC20TransferHelper : retrieve new offer
end

OffersV1 -> OffersV1 : emit OfferUpdated()

@enduml

0 comments on commit 43ffff7

Please sign in to comment.