Your First Smart Contract
Let's write a simple contract
We are going to look at a classic "Hello World" contract, but for blockchains: a simple Storage contract that lets anyone save a message and read the current message.
Here is the entire contract:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
contract SimpleStorage {
// A state variable permanently stored on the blockchain
string public message;
// A function to update the message
function setMessage(string memory _newMessage) public {
message = _newMessage;
}
}
Line-by-line breakdown
Let's tear this apart to understand exactly how Solidity works.
1. The License and Pragma
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
The first line is a machine-readable comment indicating the open-source license (MIT). The second line, the pragma, tells the compiler: "Only compile this code if you are using Solidity version 0.8.19 or higher." This prevents your code from breaking if future compiler versions change how things work.
2. Contract Declaration
contract SimpleStorage {
Think of contract exactly like class in Python or Java. It defines the blueprint. Everything inside the curly braces belongs to this contract.
3. State Variables
string public message;
This is a state variable. Because it is declared inside the contract but outside any function, it is permanently stored on the Ethereum blockchain.
string: The data type. It holds text.public: An access modifier. By declaring it public, Solidity automatically creates a hidden function that allows anyone in the world to read the value ofmessage.message: The name we gave the variable.
4. Functions
function setMessage(string memory _newMessage) public {
message = _newMessage;
}
This is a function that allows users to change the message.
function setMessage(...): We name the function.(string memory _newMessage): The parameters. We expect a string. The keywordmemorytells the EVM to store this temporary variable in memory while the function executes, rather than saving it to the permanent blockchain storage.public: Anyone can call this function.message = _newMessage;: We take the input and overwrite our permanent state variable.
Adding Access Control
Right now, anyone can call setMessage. What if we only want the person who created the contract to change the message? We introduce msg.sender and a constructor.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
contract OwnedStorage {
string public message;
address public owner;
// Runs once when the contract is deployed
constructor() {
owner = msg.sender;
}
function setMessage(string memory _newMessage) public {
// Require checks a condition. If false, it reverts the entire transaction.
require(msg.sender == owner, "Only the owner can set the message");
message = _newMessage;
}
}
What changed?
address public owner;: We added a state variable of typeaddressto hold an Ethereum wallet address (like0x123...).constructor(): This is a special function that runs only once, exactly when the contract is deployed. We set theownervariable tomsg.sender.msg.sender: A global variable that always contains the address of the person calling the function. During deployment,msg.senderis the deployer.require(...): A gatekeeper. When someone callssetMessage, it checks if the caller (msg.sender) matches theowner. If it doesn't match, the transaction fails immediately, the error string is returned, and any state changes are reversed.
Key takeaways
pragmalocks your compiler version.- State variables are permanently stored on the blockchain.
publicvariables automatically get read functions.msg.senderidentifies who is calling the contract.requireis used to enforce rules and access control.
Quiz: Your First Smart Contract
1 / 5What does the 'pragma solidity' line do?