Sıfırdan başlayarak Ethereum blockchain üzerinde akıllı sözleşme geliştirmeyi öğrenin
ETH Fiyatı
(Yaklaşık)
Aktif Smart
Contract
Ortalama
Gas Fiyatı
Smart Contract (Akıllı Sözleşme), Ethereum blockchain ağı üzerinde çalışan, önceden tanımlanmış koşulları otomatik olarak yerine getiren programlardır. Bu sözleşmeler, merkezi bir otoriteye ihtiyaç duymadan güvenli ve şeffaf işlemler yapılmasını sağlar.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
contract SimpleStorage {
// State variable
uint256 private favoriteNumber;
// Events
event NumberChanged(uint256 newNumber, address changer);
// Function to store a number
function store(uint256 _favoriteNumber) public {
favoriteNumber = _favoriteNumber;
emit NumberChanged(_favoriteNumber, msg.sender);
}
// Function to retrieve the number
function retrieve() public view returns (uint256) {
return favoriteNumber;
}
}
pragma solidity ^0.8.19;
contract DataTypes {
// Elementary types
bool public isActive = true;
uint256 public myUint = 123;
int256 public myInt = -123;
address public myAddress = 0x1234567890123456789012345678901234567890;
bytes32 public myBytes = "Hello World";
string public myString = "Hello Ethereum";
// Arrays
uint256[] public dynamicArray;
uint256[5] public fixedArray;
// Mappings
mapping(address => uint256) public balances;
mapping(address => mapping(address => bool)) public approvals;
// Structs
struct Person {
string name;
uint256 age;
bool isActive;
}
Person[] public people;
mapping(address => Person) public personMapping;
// Enums
enum Status {
Pending,
Active,
Inactive
}
Status public currentStatus = Status.Pending;
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
contract MyToken is IERC20 {
mapping(address => uint256) private _balances;
mapping(address => mapping(address => uint256)) private _allowances;
string public name = "My Token";
string public symbol = "MTK";
uint8 public decimals = 18;
uint256 private _totalSupply;
address public owner;
modifier onlyOwner() {
require(msg.sender == owner, "Not the owner");
_;
}
constructor(uint256 _initialSupply) {
owner = msg.sender;
_totalSupply = _initialSupply * 10**decimals;
_balances[msg.sender] = _totalSupply;
emit Transfer(address(0), msg.sender, _totalSupply);
}
function totalSupply() public view override returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view override returns (uint256) {
return _balances[account];
}
function transfer(address recipient, uint256 amount) public override returns (bool) {
require(recipient != address(0), "Transfer to zero address");
require(_balances[msg.sender] >= amount, "Insufficient balance");
_balances[msg.sender] -= amount;
_balances[recipient] += amount;
emit Transfer(msg.sender, recipient, amount);
return true;
}
function approve(address spender, uint256 amount) public override returns (bool) {
_allowances[msg.sender][spender] = amount;
emit Approval(msg.sender, spender, amount);
return true;
}
function allowance(address owner, address spender) public view override returns (uint256) {
return _allowances[owner][spender];
}
function transferFrom(address sender, address recipient, uint256 amount) public override returns (bool) {
require(_allowances[sender][msg.sender] >= amount, "Transfer amount exceeds allowance");
require(_balances[sender] >= amount, "Insufficient balance");
_balances[sender] -= amount;
_balances[recipient] += amount;
_allowances[sender][msg.sender] -= amount;
emit Transfer(sender, recipient, amount);
return true;
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
contract MyNFT is ERC721, Ownable {
using Counters for Counters.Counter;
Counters.Counter private _tokenIdCounter;
mapping(uint256 => string) private _tokenURIs;
uint256 public maxSupply = 10000;
uint256 public mintPrice = 0.01 ether;
constructor() ERC721("My NFT Collection", "MNC") {}
function mint(address to, string memory tokenURI) public payable {
require(_tokenIdCounter.current() < maxSupply, "Max supply reached");
require(msg.value >= mintPrice, "Insufficient payment");
uint256 tokenId = _tokenIdCounter.current();
_tokenIdCounter.increment();
_safeMint(to, tokenId);
_setTokenURI(tokenId, tokenURI);
}
function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal {
require(_exists(tokenId), "Token does not exist");
_tokenURIs[tokenId] = _tokenURI;
}
function tokenURI(uint256 tokenId) public view override returns (string memory) {
require(_exists(tokenId), "Token does not exist");
return _tokenURIs[tokenId];
}
function withdraw() public onlyOwner {
uint256 balance = address(this).balance;
payable(owner()).transfer(balance);
}
}
Smart contract'ları deploy etmeden önce mutlaka security audit yapın. Reentrancy, Integer Overflow/Underflow, Access Control gibi yaygın güvenlik açıklarına dikkat edin.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
contract StakingContract is ReentrancyGuard {
IERC20 public stakingToken;
IERC20 public rewardToken;
uint256 public rewardRate = 100; // 100 tokens per second
uint256 public lastUpdateTime;
uint256 public rewardPerTokenStored;
mapping(address => uint256) public userRewardPerTokenPaid;
mapping(address => uint256) public rewards;
mapping(address => uint256) public balances;
uint256 private _totalSupply;
event Staked(address indexed user, uint256 amount);
event Withdrawn(address indexed user, uint256 amount);
event RewardPaid(address indexed user, uint256 reward);
constructor(address _stakingToken, address _rewardToken) {
stakingToken = IERC20(_stakingToken);
rewardToken = IERC20(_rewardToken);
}
modifier updateReward(address account) {
rewardPerTokenStored = rewardPerToken();
lastUpdateTime = block.timestamp;
if (account != address(0)) {
rewards[account] = earned(account);
userRewardPerTokenPaid[account] = rewardPerTokenStored;
}
_;
}
function rewardPerToken() public view returns (uint256) {
if (_totalSupply == 0) {
return rewardPerTokenStored;
}
return rewardPerTokenStored +
(((block.timestamp - lastUpdateTime) * rewardRate * 1e18) / _totalSupply);
}
function earned(address account) public view returns (uint256) {
return ((balances[account] *
(rewardPerToken() - userRewardPerTokenPaid[account])) / 1e18) +
rewards[account];
}
function stake(uint256 amount) external nonReentrant updateReward(msg.sender) {
require(amount > 0, "Cannot stake 0");
_totalSupply += amount;
balances[msg.sender] += amount;
stakingToken.transferFrom(msg.sender, address(this), amount);
emit Staked(msg.sender, amount);
}
function withdraw(uint256 amount) public nonReentrant updateReward(msg.sender) {
require(amount > 0, "Cannot withdraw 0");
require(balances[msg.sender] >= amount, "Insufficient balance");
_totalSupply -= amount;
balances[msg.sender] -= amount;
stakingToken.transfer(msg.sender, amount);
emit Withdrawn(msg.sender, amount);
}
function getReward() public nonReentrant updateReward(msg.sender) {
uint256 reward = rewards[msg.sender];
if (reward > 0) {
rewards[msg.sender] = 0;
rewardToken.transfer(msg.sender, reward);
emit RewardPaid(msg.sender, reward);
}
}
function exit() external {
withdraw(balances[msg.sender]);
getReward();
}
}
// Web3.js ile contract etkileşimi
import Web3 from 'web3';
const contractABI = [/* Contract ABI */];
const contractAddress = '0x...';
class Web3Service {
constructor() {
this.web3 = null;
this.contract = null;
this.account = null;
}
async init() {
// MetaMask kontrolü
if (window.ethereum) {
this.web3 = new Web3(window.ethereum);
await window.ethereum.enable();
const accounts = await this.web3.eth.getAccounts();
this.account = accounts[0];
this.contract = new this.web3.eth.Contract(
contractABI,
contractAddress
);
} else {
throw new Error('MetaMask not found');
}
}
async mintNFT(tokenURI) {
const mintPrice = await this.contract.methods.mintPrice().call();
return await this.contract.methods
.mint(this.account, tokenURI)
.send({
from: this.account,
value: mintPrice,
gas: 300000
});
}
async getBalance() {
return await this.contract.methods
.balanceOf(this.account)
.call();
}
async stake(amount) {
const weiAmount = this.web3.utils.toWei(amount.toString(), 'ether');
return await this.contract.methods
.stake(weiAmount)
.send({
from: this.account,
gas: 200000
});
}
}
// Kullanım örneği
const web3Service = new Web3Service();
document.getElementById('connectWallet').onclick = async () => {
try {
await web3Service.init();
console.log('Wallet connected:', web3Service.account);
} catch (error) {
console.error('Connection failed:', error);
}
};
document.getElementById('mintNFT').onclick = async () => {
try {
const tokenURI = 'https://ipfs.io/ipfs/QmYourHash';
const tx = await web3Service.mintNFT(tokenURI);
console.log('NFT minted:', tx.transactionHash);
} catch (error) {
console.error('Minting failed:', error);
}
};
// test/MyToken.test.js
const { expect } = require("chai");
const { ethers } = require("hardhat");
describe("MyToken", function () {
let myToken;
let owner;
let addr1;
let addr2;
beforeEach(async function () {
[owner, addr1, addr2] = await ethers.getSigners();
const MyToken = await ethers.getContractFactory("MyToken");
myToken = await MyToken.deploy(1000000); // 1M tokens
await myToken.deployed();
});
describe("Deployment", function () {
it("Should set the right owner", async function () {
expect(await myToken.owner()).to.equal(owner.address);
});
it("Should assign the total supply of tokens to the owner", async function () {
const ownerBalance = await myToken.balanceOf(owner.address);
expect(await myToken.totalSupply()).to.equal(ownerBalance);
});
});
describe("Transactions", function () {
it("Should transfer tokens between accounts", async function () {
await myToken.transfer(addr1.address, 50);
const addr1Balance = await myToken.balanceOf(addr1.address);
expect(addr1Balance).to.equal(50);
await myToken.connect(addr1).transfer(addr2.address, 50);
const addr2Balance = await myToken.balanceOf(addr2.address);
expect(addr2Balance).to.equal(50);
});
it("Should fail if sender doesn't have enough tokens", async function () {
const initialOwnerBalance = await myToken.balanceOf(owner.address);
await expect(
myToken.connect(addr1).transfer(owner.address, 1)
).to.be.revertedWith("Insufficient balance");
expect(await myToken.balanceOf(owner.address)).to.equal(
initialOwnerBalance
);
});
});
});
// scripts/deploy.js
const hre = require("hardhat");
async function main() {
// Contract'ı derle
await hre.run('compile');
// Deploy edilecek parametreler
const initialSupply = 1000000;
// Contract factory'yi al
const MyToken = await hre.ethers.getContractFactory("MyToken");
// Deploy et
console.log("Deploying MyToken...");
const myToken = await MyToken.deploy(initialSupply);
// Deployment'in tamamlanmasını bekle
await myToken.deployed();
console.log("MyToken deployed to:", myToken.address);
console.log("Owner:", await myToken.owner());
console.log("Total Supply:", await myToken.totalSupply());
// Contract'ı verify et (Etherscan için)
if (network.name !== "hardhat") {
console.log("Verifying contract on Etherscan...");
try {
await hre.run("verify:verify", {
address: myToken.address,
constructorArguments: [initialSupply],
});
} catch (error) {
console.log("Verification failed:", error);
}
}
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});