This repository has been archived by the owner on Dec 23, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 70
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #126 from ourzora/offers
[feat] Offers v1.0
Showing
14 changed files
with
1,166 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
166 changes: 166 additions & 0 deletions
166
contracts/test/modules/Offers/V1/Offers.integration.t.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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| | ||
`-' `--------' `-------------------' | ||
/|\ | ||
| | ||
/ \ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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| | ||
`-' `--------' `-------------------' | ||
/|\ | ||
| | ||
/ \ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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| | ||
`-' `--------' `--------------------' | ||
/|\ | ||
| | ||
/ \ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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| | ||
`-' `--------' `-------------------' | ||
/|\ | ||
| | ||
/ \ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |