Project Members:

Sophie Westfahl, Hannes Schweiger, Edmund Radlbauer

My Roles:

Smart Contract Programming, Video Creator, Testing

During the one-week Creative Media Summer workshop, we immersed ourselves in the world of blockchain and smart contracts. Day one introduced us to the fundamentals, day two saw us programming our own blockchain, and by the third day, we delved into smart contracts. Armed with this knowledge, we spent the next 1.5 days developing our own project - Web3DStore, a unique platform for trading 3D model NFTs. The results of this intense period of innovation and teamwork, which we'll delve into more technically later, are now ready for you to explore.

Let the show begin:

2 minute project video


Imagine being a game developer in the pursuit of distinct 3D models for your game. Upon purchasing them from any 3D Asset Store, you run the risk of finding that the model has already been used in another game, recognized by the players, thus compromising its uniqueness. Furthermore, if your project direction changes, you are left holding a license for an asset you no longer require.

This is why we conceived Web3DShop. The primary benefit of this platform is that it ensures unambiguous ownership of a 3D model and its associated license via blockchain notation. It employs smart contracts to manage NFTs. Should you no longer require the 3D model, you have the option to resell the license. The ingenious part is that the original designer continues to benefit, receiving a portion of the resale price.

Homepage of Web3DShop

Technical Implementation

We used several frameworks to implement our project:

                    // SPDX-License-Identifier: MIT
                    pragma solidity ^0.8.6;
                    import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
                    import "@openzeppelin/contracts/utils/Counters.sol";
                    contract MyNFT is ERC721 {
                        using Counters for Counters.Counter;
                        Counters.Counter private _tokenIds;
                        mapping(uint256 => Item) public items;
                        uint256[] public itemIDs; // New array to store item IDs
                        string[] public itemNames;
                        string[] public itemDescriptions;
                        string[] public itemCDIs;
                        mapping(address => uint256) public authorEarnings;
                        struct Item {
                            uint256 id;
                            string name;
                            string description;
                            uint256 price;
                            address author;
                            address payable seller;
                            string cdi;
                            bool isAvailable;
                        constructor() ERC721("MyNFT", "MNFT") {
                        function createItem(string memory name, string memory description, uint256 price, string memory cdi) public returns (uint256) {
                            uint256 newItemId = _tokenIds.current();
                            _mint(msg.sender, newItemId);
                            Item memory newItem = Item({
                                id: newItemId,
                                name: name,
                                description: description,
                                price: price,
                                author: msg.sender,
                                seller: payable(msg.sender),
                                cdi: cdi,
                                isAvailable: true
                            items[newItemId] = newItem;
                            itemIDs.push(newItemId); // Store new item ID
                            return newItemId;
                        function buyItem(uint256 itemId) public payable {
                            Item storage item = items[itemId];
                            require(item.isAvailable, "Item not available");
                            require(msg.value >= item.price, "Price not met");
                            // Transfer the NFT from the seller to the buyer
                            _transfer(item.seller, msg.sender, itemId);
                            // Pay the seller and the author
                            uint256 authorPayment = (item.price * 20) / 100;
                            uint256 sellerPayment = item.price - authorPayment;
                            authorEarnings[item.author] += authorPayment;
                            // Update the seller field for the item
                            items[itemId].seller = payable(msg.sender);
                            items[itemId].isAvailable = false;
                        function makeAvailable(uint256 itemId, uint256 newPrice) public {
                            Item storage item = items[itemId];
                            require(msg.sender == item.seller, "Only the owner can make the item available");
                            item.isAvailable = true;
                            item.price = newPrice;
                        function getAllItems() public view returns (uint256[] memory, string[] memory, string[] memory, string[] memory) {
                            return (itemIDs, itemNames, itemDescriptions, itemCDIs);
                        function getItemDetails(uint256 itemId) public view returns (uint256, string memory, string memory, uint256, address, address, string memory, bool) {
                            Item storage item = items[itemId];
                            return (item.id, item.name, item.description, item.price, item.author, item.seller, item.cdi, item.isAvailable);
Smart Contract coded with Solidity