Introduction
This tutorial will introduce you to the fascinating world of decentralized sneaker trading powered by the Footwears contract. This Solidity smart contract is designed to change the way we interact with sneakers by leveraging the Ethereum blockchain and adhering to the ERC-20 token standard.
The Footwears contract will help you understand the power of decentralized applications and how blockchain technology can transform the sneaker community. Whether you’re a sneakerhead or a blockchain expert, this tutorial will pique your interest and take you on a journey where fashion meets technology.
So, are you prepared to learn the intricacies of decentralized sneaker trading? Let’s get started with the tutorial and embark on an exciting journey with the Footwears contract. Prepare to enter a world where sneakers serve as digital tokens of passion and expression. Let’s get the fun started!
Prerequisite
Before beginning this tutorial, it is necessary to have a fundamental understanding of the following concepts and technologies:
-
Solidity: Knowledge of the Solidity programming language, which is used to create smart contracts on the Ethereum blockchain, will be advantageous. Understanding data types, functions, mappings, and events will help you understand the complexities of the Footwears contract.
-
Ethereum and ERC-20 Tokens: This tutorial will be built on a solid foundation of fundamental knowledge of the Ethereum blockchain and its ecosystem, as well as knowledge of ERC-20 tokens. Understanding concepts like wallet addresses, gas fees, and token transfers will improve your learning experience.
-
Decentralized Applications (dApps): It is recommended that you are familiar with the concept of decentralized applications and their advantages over traditional centralized systems. Understanding the decentralization, immutability, and transparency principles will help you appreciate the significance of the Footwears contract.
-
Development Environment: It is critical to set up a development environment for Ethereum smart contract development. A working installation of a Solidity compiler, such as Solc, and an Ethereum development framework, such as Remix, Truffle, or Hardhat, is required. These tools will allow you to locally compile, deploy, and interact with smart contracts.
By completing these prerequisites, you will be prepared to dive into the tutorial and fully explore the exciting world of decentralized sneaker trading with the Footwears contract.
Requirements
Smart Contract
Now let’s begin writing our smart contract on Remix. The complete contract code should look like this, but I will keep updating it as the day goes by, so make sure you check out the source code repo for the updated smart contract:
// SPDX-License-Identifier: MIT
pragma solidity >=0.7.0 <0.9.0;
interface IERC20Token {
function transfer(address, uint256) external returns (bool);
function approve(address, uint256) external returns (bool);
function transferFrom(
address,
address,
uint256
) external returns (bool);
function totalSupply() external view returns (uint256);
function balanceOf(address) external view returns (uint256);
function allowance(address, address) external view returns (uint256);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(
address indexed owner,
address indexed spender,
uint256 value
);
}
contract Footwears {
uint private sneakersLength = 0;
address private cUsdTokenAddress =
0x874069Fa1Eb16D44d622F2e0Ca25eeA172369bC1;
event likeSneakerEvent(address indexed userAddress, uint256 index);
event dislikeSneakerEvent(address indexed userAddress, uint256 index);
event deleteSneakerEvent(uint256 sneakerId);
event buySneakerEvent(
address indexed seller,
address indexed buyer,
uint256 index
);
event addSneakerEvent(address indexed owner, uint256 sneakerId);
struct Sneaker {
address payable owner;
string image;
string name;
string description;
uint price;
uint likesCount;
}
mapping(uint => Sneaker) internal sneakers;
mapping(uint256 => mapping(address => bool)) likes; // sneakers liked by all users
// function to use to add sneakers
function addSneaker(
string calldata _image,
string calldata _name,
string calldata _description,
uint _price
) external {
require(bytes(_image).length > 0, "Empty image");
require(bytes(_name).length > 0, "Empty name");
require(bytes(_description).length > 0, "Empty description");
require(_price > 0, "Price needs to be at least one wei");
uint _likesCount = 0;
sneakers[sneakersLength] = Sneaker(
payable(msg.sender),
_image,
_name,
_description,
_price,
_likesCount
);
emit addSneakerEvent(msg.sender, sneakersLength);
sneakersLength++;
}
function getSneaker(uint _index)
public
view
returns (
address payable,
string memory,
string memory,
string memory,
uint,
uint
)
{
return (
sneakers[_index].owner,
sneakers[_index].image,
sneakers[_index].name,
sneakers[_index].description,
sneakers[_index].price,
sneakers[_index].likesCount
);
}
// Remove sneaker with key `_index` from `sneakers` mapping
function removeSneaker(uint256 _index) external {
require(msg.sender == sneakers[_index].owner, "Only owner can delete");
delete sneakers[_index];
emit deleteSneakerEvent(_index);
}
// Like sneaker with key `_index`
function likedSneakerEvent(uint256 _index) external {
require(_index < sneakersLength, "Sneaker does not exist");
require(!likes[_index][msg.sender], "Sneaker already liked");
likes[_index][msg.sender] = true;
sneakers[_index].likesCount++;
emit likeSneakerEvent(msg.sender, _index);
}
// Get total likes for sneaker with key `_index`
function getTotalLikes(uint256 _index) external view returns (uint256) {
require(_index < sneakersLength, "Invalid index");
return sneakers[_index].likesCount;
}
// Get total sneakers count
function getTotalSneakers() external view returns (uint256) {
return sneakersLength;
}
}
Breakdown
// SPDX-License-Identifier: MIT
pragma solidity >=0.7.0 <0.9.0;
- First, we declared our
license
and theSolidity version
.
interface IERC20Token {
function transfer(address, uint256) external returns (bool);
function approve(address, uint256) external returns (bool);
function transferFrom(
address,
address,
uint256
) external returns (bool);
function totalSupply() external view returns (uint256);
function balanceOf(address) external view returns (uint256);
function allowance(address, address) external view returns (uint256);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(
address indexed owner,
address indexed spender,
uint256 value
);
}
- The
interface
specifies a set of functions and events that a contract must support in order to be classified as an ERC-20 token. ERC-20 is a widely used token standard on the Ethereum blockchain that ensures interoperability among various tokens and applications.
contract Footwears {
uint private sneakersLength = 0;
address private cUsdTokenAddress =
0x874069Fa1Eb16D44d622F2e0Ca25eeA172369bC1;
event likeSneakerEvent(address indexed userAddress, uint256 index);
event dislikeSneakerEvent(address indexed userAddress, uint256 index);
event deleteSneakerEvent(uint256 sneakerId);
event buySneakerEvent(
address indexed seller,
address indexed buyer,
uint256 index
);
event addSneakerEvent(address indexed owner, uint256 sneakerId);
- Contract Footwears
The Footwears contract is the framework for decentralized sneaker trading. It adds new features and events to help with sneaker management and interaction.
-
sneakersLength
: The total number of sneakers added to the platform is stored in this variable. -
cUsdTokenAddress
: If an external cUSD token exists, the contract assigns its address to this variable. It enables potential integration and interaction between the Footwears and cUSD token contracts. -
Events
: Several events are defined in the contract, including likeSneakerEvent, dislikeSneakerEvent, deleteSneakerEvent, buySneakerEvent, and addSneakerEvent. These events are emitted during specific actions, allowing interested parties to track and notify them of the occurrences.
struct Sneaker {
address payable owner;
string image;
string name;
string description;
uint price;
uint likesCount;
}
Struct Sneaker
: This structure defines a sneaker’s properties, such as the owner’s address, image, name, description, price, and likesCount. It acts as a template for creating and storing sneaker objects.
mapping(uint => Sneaker) internal sneakers;
mapping(uint256 => mapping(address => bool)) likes; // sneakers liked by all users
Mappings
: The contract makes use of two mappings. The first converts an uint (sneaker ID) to a Sneaker object, allowing for quick retrieval and management of sneaker information. The second converts a sneaker ID and an address into a boolean value that indicates whether a user has liked a specific sneaker.
function addSneaker(
string calldata _image,
string calldata _name,
string calldata _description,
uint _price
) external {
require(bytes(_image).length > 0, "Empty image");
require(bytes(_name).length > 0, "Empty name");
require(bytes(_description).length > 0, "Empty description");
require(_price > 0, "Price needs to be at least one wei");
uint _likesCount = 0;
sneakers[sneakersLength] = Sneaker(
payable(msg.sender),
_image,
_name,
_description,
_price,
_likesCount
);
emit addSneakerEvent(msg.sender, sneakersLength);
sneakersLength++;
}
- The
addSneaker function
allows users to add sneakers to the platform. It validates the inputs, generates a new Sneaker object, and emits the addSneakerEvent to notify others of the addition.
function getSneaker(uint _index)
public
view
returns (
address payable,
string memory,
string memory,
string memory,
uint,
uint
)
{
return (
sneakers[_index].owner,
sneakers[_index].image,
sneakers[_index].name,
sneakers[_index].description,
sneakers[_index].price,
sneakers[_index].likesCount
);
}
getSneaker Function
: Retrieves the details of a sneaker from the sneakers mapping at a specific index and returns them as a tuple.
// Remove sneaker with key `_index` from `sneakers` mapping
function removeSneaker(uint256 _index) external {
require(msg.sender == sneakers[_index].owner, "Only owner can delete");
delete sneakers[_index];
emit deleteSneakerEvent(_index);
}
removeSneaker Function
: Allows the sneaker’s owner to delete it from the platform. This function can only be activated by the owner, ensuring ownership control.
// Like sneaker with key `_index`
function likedSneakerEvent(uint256 _index) external {
require(_index < sneakersLength, "Sneaker does not exist");
require(!likes[_index][msg.sender], "Sneaker already liked");
likes[_index][msg.sender] = true;
sneakers[_index].likesCount++;
emit likeSneakerEvent(msg.sender, _index);
}
likedSneakerEvent Function
: This function allows users to like a sneaker by increasing its likesCount and emitting the likeSneakerEvent. A user can only like one sneaker at a time.
// Get total likes for sneaker with key `_index`
function getTotalLikes(uint256 _index) external view returns (uint256) {
require(_index < sneakersLength, "Invalid index");
return sneakers[_index].likesCount;
}
Function getTotalLikes
: Returns the total number of likes for a given sneaker index.
// Get total sneakers count
function getTotalSneakers() external view returns (uint256) {
return sneakersLength;
}
}
getTotalSneakers Function
: Returns the total number of sneakers that have been added to the platform.
Deployment
In your deploy.js
file delete everything and add this code:
module.exports = async ({ getNamedAccounts, deployments }) => {
const { deploy } = deployments;
const { deployer } = await getNamedAccounts();
await deploy("Footwears", {
from: deployer,
args: [], // remove the argument
log: true,
});
};
module.exports.tags = ["Footwears"];
-
To deploy our smart contract successfully, we need the Celo extension wallet, which can be downloaded from here
-
Next, we need to fund our newly created wallet, which can be done using the Celo Alfajores faucet here
-
You can now fund your wallet and deploy your contract using the Celo plugin in Remix.
Conclusion
Congratulations on finishing the overview of the Footwears contract! You’ve delved into the intriguing world of decentralized sneaker trading, learning about the inner workings of this innovative smart contract.
You’ve seen the power of Solidity and the Ethereum blockchain revolutionizing the sneaker industry throughout this tutorial. The Footwears contract has introduced you to a world in which sneakers are transformed into digital tokens, allowing for secure ownership, transparent transactions, and even community engagement via likes.
You are now prepared to explore further and build on the Footwears contract after mastering the concepts covered in this tutorial. You understand how to add new sneakers, retrieve their information, manage likes, and even extend the functionality to create a more robust decentralized sneaker trading platform.
Keep in mind that the potential of blockchain technology extends beyond sneakers. This newfound understanding of smart contracts can be applied to a variety of domains, allowing the development of decentralized applications that reshape traditional industries.
Don’t forget to unleash your creativity and explore the limitless possibilities that await you as you continue your journey into the world of blockchain development and decentralized applications. Accept the spirit of innovation and use your newly acquired knowledge to effect positive change in the world.
It’s now time to put your skills to the test, play with the Footwears contract, and let your imagination run wild. The Footwears contract has laid the groundwork for you to embark on a transformative journey, whether you choose to build on it, integrate it with other contracts, or explore new horizons.
So go forth, keep learning, and help shape the decentralized future. The world is looking forward to your creative ideas and contributions. Happy coding, and may your journey be filled with exciting discoveries and historic accomplishments!