-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathCrowdfundFactory.sol
131 lines (121 loc) · 4.89 KB
/
CrowdfundFactory.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
// SPDX-License-Identifier: Beta Software
pragma solidity ^0.8;
import "../globals/IGlobals.sol";
import "../utils/LibRawResult.sol";
import "../utils/Proxy.sol";
import "./AuctionCrowdfund.sol";
import "./BuyCrowdfund.sol";
import "./CollectionBuyCrowdfund.sol";
/// @notice Factory used to deploys new proxified `Crowdfund` instances.
contract CrowdfundFactory {
using LibRawResult for bytes;
event BuyCrowdfundCreated(BuyCrowdfund crowdfund, BuyCrowdfund.BuyCrowdfundOptions opts);
event AuctionCrowdfundCreated(AuctionCrowdfund crowdfund, AuctionCrowdfund.AuctionCrowdfundOptions opts);
event CollectionBuyCrowdfundCreated(CollectionBuyCrowdfund crowdfund, CollectionBuyCrowdfund.CollectionBuyCrowdfundOptions opts);
// The `Globals` contract storing global configuration values. This contract
// is immutable and it’s address will never change.
IGlobals private immutable _GLOBALS;
// Set the `Globals` contract.
constructor(IGlobals globals) {
_GLOBALS = globals;
}
/// @notice Create a new crowdfund to purchases a specific NFT (i.e., with a
/// known token ID) listing for a known price.
/// @param opts Options used to initialize the crowdfund. These are fixed
/// and cannot be changed later.
/// @param createGateCallData Encoded calldata used by `createGate()` to
/// create the crowdfund if one is specified in `opts`.
function createBuyCrowdfund(
BuyCrowdfund.BuyCrowdfundOptions memory opts,
bytes memory createGateCallData
)
public
payable
returns (BuyCrowdfund inst)
{
opts.gateKeeperId = _prepareGate(
opts.gateKeeper,
opts.gateKeeperId,
createGateCallData
);
inst = BuyCrowdfund(payable(new Proxy{ value: msg.value }(
_GLOBALS.getImplementation(LibGlobals.GLOBAL_BUY_CF_IMPL),
abi.encodeCall(BuyCrowdfund.initialize, (opts))
)));
emit BuyCrowdfundCreated(inst, opts);
}
/// @notice Create a new crowdfund to bid on an auction for a specific NFT
/// (i.e. with a known token ID).
/// @param opts Options used to initialize the crowdfund. These are fixed
/// and cannot be changed later.
/// @param createGateCallData Encoded calldata used by `createGate()` to create
/// the crowdfund if one is specified in `opts`.
function createAuctionCrowdfund(
AuctionCrowdfund.AuctionCrowdfundOptions memory opts,
bytes memory createGateCallData
)
public
payable
returns (AuctionCrowdfund inst)
{
opts.gateKeeperId = _prepareGate(
opts.gateKeeper,
opts.gateKeeperId,
createGateCallData
);
inst = AuctionCrowdfund(payable(new Proxy{ value: msg.value }(
_GLOBALS.getImplementation(LibGlobals.GLOBAL_AUCTION_CF_IMPL),
abi.encodeCall(AuctionCrowdfund.initialize, (opts))
)));
emit AuctionCrowdfundCreated(inst, opts);
}
/// @notice Create a new crowdfund to purchases any NFT from a collection
/// (i.e. any token ID) from a collection for a known price.
/// @param opts Options used to initialize the crowdfund. These are fixed
/// and cannot be changed later.
/// @param createGateCallData Encoded calldata used by `createGate()` to create
/// the crowdfund if one is specified in `opts`.
function createCollectionBuyCrowdfund(
CollectionBuyCrowdfund.CollectionBuyCrowdfundOptions memory opts,
bytes memory createGateCallData
)
public
payable
returns (CollectionBuyCrowdfund inst)
{
opts.gateKeeperId = _prepareGate(
opts.gateKeeper,
opts.gateKeeperId,
createGateCallData
);
inst = CollectionBuyCrowdfund(payable(new Proxy{ value: msg.value }(
_GLOBALS.getImplementation(LibGlobals.GLOBAL_COLLECTION_BUY_CF_IMPL),
abi.encodeCall(CollectionBuyCrowdfund.initialize, (opts))
)));
emit CollectionBuyCrowdfundCreated(inst, opts);
}
function _prepareGate(
IGateKeeper gateKeeper,
bytes12 gateKeeperId,
bytes memory createGateCallData
)
private
returns (bytes12 newGateKeeperId)
{
if (
address(gateKeeper) == address(0) ||
gateKeeperId != bytes12(0)
) {
// Using an existing gate on the gatekeeper
// or not using a gate at all.
return gateKeeperId;
}
// Call the gate creation function on the gatekeeper.
(bool s, bytes memory r) = address(gateKeeper).call(createGateCallData);
if (!s) {
r.rawRevert();
}
// Result is always a bytes12.
return abi.decode(r, (bytes12));
}
}