Skip to content

Commit 1315bf8

Browse files
committed
save dulu
1 parent d29411b commit 1315bf8

7 files changed

Lines changed: 628 additions & 634 deletions

File tree

script/deploy.s.sol

Lines changed: 62 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,62 +1,62 @@
1-
// SPDX-License-Identifier: MIT
2-
pragma solidity ^0.8.23;
3-
4-
import {Script} from "forge-std/Script.sol";
5-
import {console} from "forge-std/console.sol";
6-
import {MasterOwnerModifier} from "../src/MasterOwnerModifier.sol";
7-
import {MasterContract} from "../src/Master.sol";
8-
import {TreasuryFund} from "../src/TreasuryFund.sol";
9-
import {MockERC20} from "../src/MockERC20.sol";
10-
11-
contract DeployScript is Script {
12-
function run() external {
13-
14-
address eth_usdc_token_testnet_address = address(0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238); // USDC testnet address
15-
address eth_usdc_token_mainnet_address = address(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48); // USDC mainnet address
16-
17-
address base_usdc_token_testnet_address = address(0x036CbD53842c5426634e7929541eC2318f3dCF7e); // USDC testnet address
18-
19-
// Ambil private key dan RPC URL dari .env
20-
uint256 deployerPrivateKey = vm.envUint("DEPLOYER_PRIVATE_KEY");
21-
string memory chain = "BASE"; // BASE, BSC, POLYGON, etc
22-
string memory network = "SEPOLIA"; // SEPOLIA, MAINNET
23-
string memory rpcUrl;
24-
25-
if (keccak256(bytes(network)) == keccak256(bytes("SEPOLIA"))) {
26-
rpcUrl = vm.envString(string.concat(chain, "_SEPOLIA_RPC_URL"));
27-
console.log(" Deploying to ",chain," Sepolia...");
28-
} else if (keccak256(bytes(network)) == keccak256(bytes("mainnet"))) {
29-
rpcUrl = vm.envString(string.concat(chain, "_MAINNET_RPC_URL"));
30-
console.log(" Deploying to ",chain," Mainnet...");
31-
} else {
32-
revert(" Unsupported network! Use 'sepolia' or 'mainnet'.");
33-
}
34-
35-
vm.startBroadcast(deployerPrivateKey);
36-
37-
// Deploy MasterOwnerModifier
38-
MasterOwnerModifier masterOwnerModifier = new MasterOwnerModifier();
39-
console.log(" MasterOwnerModifier deployed at:", address(masterOwnerModifier));
40-
41-
// Deploy TreasuryFund
42-
TreasuryFund treasuryFund = new TreasuryFund();
43-
console.log("TreasuryFund deployed at:", address(treasuryFund));
44-
45-
// Deploy MasterContract
46-
MasterContract masterContract = new MasterContract(
47-
address(treasuryFund),
48-
base_usdc_token_testnet_address,
49-
address(masterOwnerModifier)
50-
);
51-
console.log("MasterContract deployed at:", address(masterContract));
52-
53-
vm.stopBroadcast();
54-
}
55-
}
56-
/*
57-
forge script script/deploy.s.sol --rpc-url $(grep ${NETWORK}_RPC_URL .env | cut -d '=' -f2) --broadcast --private-key $DEPLOYER_PRIVATE_KEY
58-
59-
auto deploy and verify
60-
forge script script/deploy.s.sol --rpc-url $BASE_SEPOLIA_RPC_URL --broadcast --private-key $DEPLOYER_PRIVATE_KEY --verify --etherscan-api-key $BASESCAN_API_KEY
61-
62-
*/
1+
// // SPDX-License-Identifier: MIT
2+
// pragma solidity ^0.8.23;
3+
4+
// import {Script} from "forge-std/Script.sol";
5+
// import {console} from "forge-std/console.sol";
6+
// import {MasterOwnerModifier} from "../src/MasterOwnerModifier.sol";
7+
// import {MasterContract} from "../src/Master.sol";
8+
// import {TreasuryFund} from "../src/TreasuryFund.sol";
9+
// import {MockERC20} from "../src/MockERC20.sol";
10+
11+
// contract DeployScript is Script {
12+
// function run() external {
13+
14+
// address eth_usdc_token_testnet_address = address(0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238); // USDC testnet address
15+
// address eth_usdc_token_mainnet_address = address(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48); // USDC mainnet address
16+
17+
// address base_usdc_token_testnet_address = address(0x036CbD53842c5426634e7929541eC2318f3dCF7e); // USDC testnet address
18+
19+
// // Ambil private key dan RPC URL dari .env
20+
// uint256 deployerPrivateKey = vm.envUint("DEPLOYER_PRIVATE_KEY");
21+
// string memory chain = "BASE"; // BASE, BSC, POLYGON, etc
22+
// string memory network = "SEPOLIA"; // SEPOLIA, MAINNET
23+
// string memory rpcUrl;
24+
25+
// if (keccak256(bytes(network)) == keccak256(bytes("SEPOLIA"))) {
26+
// rpcUrl = vm.envString(string.concat(chain, "_SEPOLIA_RPC_URL"));
27+
// console.log(" Deploying to ",chain," Sepolia...");
28+
// } else if (keccak256(bytes(network)) == keccak256(bytes("mainnet"))) {
29+
// rpcUrl = vm.envString(string.concat(chain, "_MAINNET_RPC_URL"));
30+
// console.log(" Deploying to ",chain," Mainnet...");
31+
// } else {
32+
// revert(" Unsupported network! Use 'sepolia' or 'mainnet'.");
33+
// }
34+
35+
// vm.startBroadcast(deployerPrivateKey);
36+
37+
// // Deploy MasterOwnerModifier
38+
// MasterOwnerModifier masterOwnerModifier = new MasterOwnerModifier();
39+
// console.log(" MasterOwnerModifier deployed at:", address(masterOwnerModifier));
40+
41+
// // Deploy TreasuryFund
42+
// TreasuryFund treasuryFund = new TreasuryFund();
43+
// console.log("TreasuryFund deployed at:", address(treasuryFund));
44+
45+
// // Deploy MasterContract
46+
// MasterContract masterContract = new MasterContract(
47+
// address(treasuryFund),
48+
// base_usdc_token_testnet_address,
49+
// address(masterOwnerModifier)
50+
// );
51+
// console.log("MasterContract deployed at:", address(masterContract));
52+
53+
// vm.stopBroadcast();
54+
// }
55+
// }
56+
// /*
57+
// forge script script/deploy.s.sol --rpc-url $(grep ${NETWORK}_RPC_URL .env | cut -d '=' -f2) --broadcast --private-key $DEPLOYER_PRIVATE_KEY
58+
59+
// auto deploy and verify
60+
// forge script script/deploy.s.sol --rpc-url $BASE_SEPOLIA_RPC_URL --broadcast --private-key $DEPLOYER_PRIVATE_KEY --verify --etherscan-api-key $BASESCAN_API_KEY
61+
62+
// */

src/EventContract.sol

Lines changed: 40 additions & 188 deletions
Original file line numberDiff line numberDiff line change
@@ -1,232 +1,84 @@
11
// SPDX-License-Identifier: MIT
22
pragma solidity ^0.8.23;
33

4+
import "@openzeppelin/contracts/access/Ownable.sol";
45
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
5-
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
6-
import "./MasterOwnerModifier.sol";
7-
8-
contract EventContract is ERC721Enumerable {
9-
address public eventOwner;
10-
address public treasuryContract;
11-
IERC20 public usdcToken;
12-
MasterOwnerModifier public masterOwnerModifier;
6+
import "./ITicketManager.sol";
137

8+
contract EventContract is ERC721Enumerable, Ownable {
9+
address public immutable usdcToken;
10+
address public immutable treasury;
11+
address public immutable masterOwnerModifier;
12+
1413
string public eventName;
15-
bytes32[] public ticketTypes;
16-
14+
bytes32 public nftSymbol;
1715
uint256 public eventStart;
1816
uint256 public eventEnd;
19-
uint256 public eventTiketStartSale;
20-
uint256 public eventTiketEndSale;
21-
uint256 public totalRevenue;
22-
uint256 private _nextTokenId = 1;
23-
17+
uint256 public ticketStartSale;
18+
uint256 public ticketEndSale;
2419
bool public isCancelled = false;
2520

26-
struct Ticket {
27-
bytes32 ticketType;
28-
uint256 price;
29-
uint256 maxSupply;
30-
uint256 minted;
31-
}
32-
33-
mapping(bytes32 => Ticket) public tickets;
34-
mapping(uint256 => bytes32) public ticketTypesById;
35-
mapping(address => bool) public additionalEventOwners;
21+
ITicketManager public ticketManager;
3622

3723
event EventCancelled(string reason);
38-
event FundsWithdrawn(address indexed vendor, uint256 vendorAmount, uint256 treasuryAmount);
39-
event TicketMinted(address indexed buyer, bytes32 ticketType, uint256 tokenId);
40-
event TicketRefunded(address indexed buyer, uint256 tokenId, uint256 amount);
41-
event TicketUsed(uint256 tokenId);
24+
event TicketUsed(uint256 indexed tokenId);
4225

43-
error EventNotCancel();
44-
error TicketSoldOut();
26+
error EventNotCancelled();
4527
error TicketSaleNotActive();
46-
error PaymentFailed();
4728
error NotTicketOwner();
4829
error EventNotOver();
49-
error NoFundsAvailable();
50-
error InvalidAddress();
51-
error NotEventOwner();
52-
error NotMasterOwner();
53-
error NotMasterOrEventOwner();
5430

55-
modifier onlyEventOwner() {
56-
if (msg.sender != eventOwner && !additionalEventOwners[msg.sender]) revert NotEventOwner();
57-
_;
58-
}
59-
60-
modifier onlyMasterOwner() {
61-
if (!masterOwnerModifier.isMasterOwner(msg.sender)) revert NotMasterOwner();
62-
_;
63-
}
64-
65-
modifier onlyVendorOrOwner() {
66-
if (msg.sender != eventOwner && !masterOwnerModifier.isMasterOwner(msg.sender)) revert NotMasterOrEventOwner();
67-
_;
68-
}
69-
70-
/**
71-
* @dev Constructor to initialize the contract.
72-
* @param _vendor Address of the event vendor.
73-
* @param _usdcToken Address of the USDC token contract.
74-
* @param _treasuryContract Address of the treasury contract.
75-
* @param _name Name of the event.
76-
* @param _nftSymbol Symbol of the NFT.
77-
* @param _start Start timestamp of the event.
78-
* @param _end End timestamp of the event.
79-
* @param _startSale Start timestamp of the ticket sale.
80-
* @param _endSale End timestamp of the ticket sale.
81-
*/
8231
constructor(
83-
address _vendor,
32+
address _owner,
8433
address _usdcToken,
85-
address _treasuryContract,
86-
address _ownerModifierAddress,
87-
bytes32 _name,
34+
address _treasury,
35+
address _masterOwnerModifier,
36+
ITicketManager _ticketManager,
37+
string memory _eventName,
8838
bytes32 _nftSymbol,
8939
uint256 _start,
9040
uint256 _end,
9141
uint256 _startSale,
9242
uint256 _endSale
93-
) ERC721(string(abi.encodePacked(_name)), string(abi.encodePacked(_nftSymbol))) {
94-
eventOwner = _vendor;
95-
usdcToken = IERC20(_usdcToken);
96-
treasuryContract = _treasuryContract;
97-
masterOwnerModifier = MasterOwnerModifier(_ownerModifierAddress);
98-
eventName = string(abi.encodePacked(_name));
43+
) ERC721(_eventName, string(abi.encodePacked(_nftSymbol))) Ownable(_owner) {
44+
usdcToken = _usdcToken;
45+
treasury = _treasury;
46+
masterOwnerModifier = _masterOwnerModifier;
47+
ticketManager = _ticketManager;
48+
eventName = _eventName;
49+
nftSymbol = _nftSymbol;
9950
eventStart = _start;
10051
eventEnd = _end;
101-
eventTiketStartSale = _startSale;
102-
eventTiketEndSale = _endSale;
103-
52+
ticketStartSale = _startSale;
53+
ticketEndSale = _endSale;
10454
}
10555

106-
function addTickets(bytes32[] calldata _ticketTypes, uint256[] calldata _prices, uint256[] calldata _maxSupplies
107-
) external onlyEventOwner {
108-
require(_ticketTypes.length == _prices.length && _ticketTypes.length == _maxSupplies.length, "Invalid ticket data");
109-
110-
for (uint256 i = 0; i < _ticketTypes.length; i++) {
111-
tickets[_ticketTypes[i]] = Ticket({
112-
ticketType: _ticketTypes[i],
113-
price: _prices[i],
114-
maxSupply: _maxSupplies[i],
115-
minted: 0
116-
});
117-
ticketTypes.push(_ticketTypes[i]);
118-
}
56+
modifier onlyDuringSale() {
57+
if (block.timestamp < ticketStartSale || block.timestamp > ticketEndSale) revert TicketSaleNotActive();
58+
_;
11959
}
12060

61+
modifier onlyTicketOwner(uint256 _tokenId) {
62+
if (ownerOf(_tokenId) != msg.sender) revert NotTicketOwner();
63+
_;
64+
}
12165

122-
/**
123-
* @dev Function to mint a new ticket.
124-
* @param _ticketType The type of the ticket to be minted.
125-
*/
126-
function mintTicket(bytes32 _ticketType) external {
127-
if (isCancelled) revert EventNotCancel();
128-
if (block.timestamp < eventTiketStartSale || block.timestamp > eventTiketEndSale) revert TicketSaleNotActive();
129-
130-
Ticket storage ticket = tickets[_ticketType];
131-
if (ticket.minted >= ticket.maxSupply) revert TicketSoldOut();
132-
if (!usdcToken.transferFrom(msg.sender, address(this), ticket.price)) revert PaymentFailed();
133-
134-
uint256 tokenId = _nextTokenId++;
135-
_safeMint(msg.sender, tokenId);
136-
ticketTypesById[tokenId] = _ticketType;
137-
ticket.minted++;
138-
totalRevenue += ticket.price;
139-
140-
emit TicketMinted(msg.sender, _ticketType, tokenId);
66+
function mintTicket(bytes32 _ticketType) external onlyDuringSale {
67+
ticketManager.mintTicket(msg.sender, _ticketType);
14168
}
14269

143-
/**
144-
* @dev Function to get all tickets owned by a user.
145-
* @param _user The address of the user.
146-
* @return ticketIds Array of ticket IDs owned by the user.
147-
* @return ticketTypesArray Array of ticket types owned by the user.
148-
*/
14970
function getUserTickets(address _user) external view returns (uint256[] memory, bytes32[] memory) {
150-
uint256 balance = balanceOf(_user);
151-
uint256[] memory ticketIds = new uint256[](balance);
152-
bytes32[] memory ticketTypesArray = new bytes32[](balance);
153-
154-
for (uint256 i = 0; i < balance; i++) {
155-
uint256 tokenId = tokenOfOwnerByIndex(_user, i);
156-
ticketIds[i] = tokenId;
157-
ticketTypesArray[i] = ticketTypesById[tokenId];
158-
}
159-
160-
return (ticketIds, ticketTypesArray);
71+
return ticketManager.getUserTickets(_user);
16172
}
16273

163-
/**
164-
* @dev Function to use a ticket.
165-
* @param _tokenId The ID of the ticket to be used.
166-
*/
167-
function useTicket(uint256 _tokenId) external {
168-
if (ownerOf(_tokenId) != msg.sender) revert NotTicketOwner();
74+
function useTicket(uint256 _tokenId) external onlyTicketOwner(_tokenId) {
16975
_burn(_tokenId);
17076
emit TicketUsed(_tokenId);
17177
}
17278

173-
/**
174-
* @dev Function to modify the max supply of a ticket type.
175-
* @param _ticketType The type of the ticket to be modified.
176-
* @param _newMaxSupply The new max supply for the ticket type.
177-
*/
178-
function modifyTicketMaxSupply(bytes32 _ticketType, uint256 _newMaxSupply) external onlyEventOwner {
179-
if (_newMaxSupply == 0) revert("Max supply must be greater than zero");
180-
Ticket storage ticket = tickets[_ticketType];
181-
if (ticket.maxSupply == 0) revert("Ticket type does not exist");
182-
if (_newMaxSupply < ticket.minted) revert("New max supply cannot be less than minted tickets");
183-
184-
ticket.maxSupply = _newMaxSupply;
185-
}
186-
187-
/**
188-
* @dev Function to withdraw funds after the event ends.
189-
*/
190-
function withdrawFunds() external onlyVendorOrOwner {
191-
if (block.timestamp <= eventEnd) revert EventNotOver();
192-
if (isCancelled) revert EventNotCancel();
193-
if (totalRevenue == 0) revert NoFundsAvailable();
194-
195-
uint256 treasuryAmount = totalRevenue / 100; // 1% for treasury
196-
uint256 vendorAmount = totalRevenue - treasuryAmount;
197-
198-
if (!usdcToken.transfer(eventOwner, vendorAmount)) revert PaymentFailed();
199-
if (!usdcToken.transfer(treasuryContract, treasuryAmount)) revert PaymentFailed();
200-
201-
emit FundsWithdrawn(eventOwner, vendorAmount, treasuryAmount);
202-
totalRevenue = 0;
203-
}
204-
205-
/**
206-
* @dev Function to cancel the event and refund all ticket holders.
207-
* @param reason The reason for cancelling the event.
208-
*/
209-
function cancelEventAndAutoRefund(string calldata reason) external onlyVendorOrOwner {
210-
if (isCancelled) revert EventNotCancel();
79+
function cancelEvent(string calldata reason) external onlyOwner {
21180
isCancelled = true;
81+
ticketManager.refundAll();
21282
emit EventCancelled(reason);
213-
// Refund all ticket holders
214-
uint256 totalSupply = totalSupply();
215-
for (uint256 i = 0; i < totalSupply; i++) {
216-
217-
uint256 tokenId = tokenByIndex(i);
218-
address ticketOwner = ownerOf(tokenId);
219-
bytes32 ticketType = ticketTypesById[tokenId];
220-
uint256 refundAmount = tickets[ticketType].price;
221-
222-
_burn(tokenId);
223-
if (!usdcToken.transfer(ticketOwner, refundAmount)) revert PaymentFailed();
224-
emit TicketRefunded(ticketOwner, tokenId, refundAmount);
225-
}
226-
totalRevenue = 0;
227-
}
228-
229-
function getTicketDetails(bytes32 ticketType) public view returns (uint256 price, uint256 supply) {
230-
return (tickets[ticketType].price, tickets[ticketType].maxSupply);
23183
}
23284
}

0 commit comments

Comments
 (0)