使用-solidity-开发第一个-以太坊智能合约
目录
使用 solidity 开发第一个 以太坊智能合约
前言
使用 solidity 开发一个以太坊区块链的智能合约,并且使用Dapp 进行交互。
项目源代码
最终效果



环境搭建
Nodejs 和 Ganache 请自行安装,然后使用npm安装 Truffle 智能合同框架,web3js
npm install -g truffle
npm install -g web3
- Ganache v7.9.1 个人区块链测试环境
- Solidity - 0.8.19 (solc-js) 以太坊区块链语言
- Node v18.14.2
- Truffle v5.11.5 (core: 5.11.5) 智能合约开发框架
- Web3.js v1.10.0
智能合约内容
我们要实现在智能合约中存储和检索一个字符串值 setGreeting() 设置值, getGreeting() 获取值
Truffle 创建项目
mkdir sc-demo # 创建目录
truffle init # 项目初始化
初始化项目会生成3个文件夹和一个 配置文件
- contracts 合同文件
- migrations 部署文件
- test 测试文件
- truffle-config.js 配置文件
Truffle 编码
使用命令创建合同文件,也可以手动创建
# 命令创建
truffle create contract HelloWorld
文件生成的路径
contracts/HelloWorld.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;
contract HelloWorld {
string public greeting;
constructor() {
greeting = "Hello world!";
}
function setGreeting(string memory _greeting) public{
greeting = _greeting;
}
function getGreeting() public view returns (string memory ){
return greeting;
}
}
Truffle 打包
修改区块链地址
truffle-config.js
// 地址是你个人区块链测试地址
development: {
host: "127.0.0.1", // Localhost (default: none)
port: 7545, // Standard Ethereum port (default: none)
network_id: "*" // Any network (default: none)
}
# 打包命令
truffle compile
Truffle 部署
迁移文件的命名规则
Truffle要求迁移文件遵循一定的命名规则,通常是以数字开头,后跟一个描述性名称,如1_initial_migration.js、2_deploy_contracts.js等。数字用于确保迁移按正确的顺序执行。
编写部署文件
migrations/2_deploy_contracts.js
const HelloWorld = artifacts.require("HelloWorld");
module.exports = function (deployer) {
deployer.deploy(HelloWorld);
};
修改编译器版本 0.8.19
compilers: {
solc: {
version: "0.8.19" // Fetch exact version from solc-bin (default: truffle's version)
// docker: true, // Use "0.5.1" you've installed locally with docker (default: false)
// settings: { // See the solidity docs for advice about optimization and evmVersion
// optimizer: {
// enabled: false,
// runs: 200
// },
// evmVersion: "byzantium"
// }
}
}
# 部署命令
truffle migrate
Truffle 测试
创建测试文件
路径 contracts/test/HelloWorld.test.js
const HelloWorld = artifacts.require("HelloWorld");
contract("HelloWorld", (accounts) => {
it("should return the initial greeting", async () => {
const instance = await HelloWorld.deployed();
const greeting = await instance.getGreeting();
assert.equal(
greeting,
"Hello, World!",
"The initial greeting is not correct"
);
});
it("should set a new greeting", async () => {
const instance = await HelloWorld.deployed();
await instance.setGreeting("Hello, Truffle!");
const greeting = await instance.getGreeting();
assert.equal(
greeting,
"Hello, Truffle!",
"The new greeting is not set correctly"
);
});
});
运行测试命令
truffle test
Dapp
使用web3js 于智能合约交互,get()获取值,set()设置值
<!DOCTYPE html>
<html>
<head>
<title>Simple Storage DApp</title>
</head>
<body>
<h1>Simple Storage DApp</h1>
<input type="text" id="storageValue">
<button onclick="set()">Set Value</button>
<button onclick="get()">Get Value</button>
<p id="value"></p>
<script src="https://cdn.jsdelivr.net/npm/web3@1.3.6/dist/web3.min.js"></script>
<script>
const web3 = new Web3(Web3.givenProvider || "http://127.0.0.1:7545");
const contractAddress = '0x0cf35631BF8B3860c0D63Fc7eB03750566023F70'; // 使用你的合约地址替换这里
// 使用你的 abi 替换这里
const contractABI = [
{
"inputs": [],
"name": "greeting",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function",
"constant": true
},
{
"inputs": [
{
"internalType": "string",
"name": "_greeting",
"type": "string"
}
],
"name": "setGreeting",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "getGreeting",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function",
"constant": true
}
] // 使用你的合约ABI替换这里
const contract = new web3.eth.Contract(contractABI, contractAddress);
async function set() {
const accounts = await web3.eth.getAccounts();
const value = document.getElementById('storageValue').value;
await contract.methods.setGreeting(value).send({ from: accounts[0] });
}
async function get() {
const value = await contract.methods.getGreeting().call();
document.getElementById('value').innerText = value;
}
</script>
</body>
</html>
命令总结
truffle init #初始化项目
truffle create contract XX #创建合同
truffle compile # 打包
truffle migrate # 部署命令
truffle console --network development # 部署完成后,你可以通过Truffle控制台与智能合约交互
truffle test # 测试
遇到的问题
注意Solidity 0.8.20
这是因为solidity 0.8.20引入了PUSH0(0x5f)操作码,该操作码仅在ETH主网上支持,而在任何其他链上都不支持。这就是为什么其他链找不到PUSH0(0x5f)操作码并抛出此错误的原因。考虑对其他链使用0.8.19。
使用-solidity-开发第一个-以太坊智能合约的更多相关文章
- 以太坊智能合约 Solidity 的常用数据类型介绍
目录 目录 1.数组 1.1.对数组的增删改查操作. 2.String.Bytes.Mapping的使用 3.Enums 和 Structs 的简单应用 4.Ether 单位和 Time 单位 5.A ...
- 以太坊智能合约开发,Web3.js API 中文文档 ethereum web3.js入门说明
以太坊智能合约开发,Web3.js API 中文文档 ethereum web3.js入门说明 为了让你的Ðapp运行上以太坊,一种选择是使用web3.js library提供的web3.对象.底层实 ...
- 以太坊智能合约介绍,Solidity介绍
以太坊智能合约介绍,Solidity介绍 一个简单的智能合约 先从一个非常基础的例子开始,不用担心你现在还一点都不了解,我们将逐步了解到更多的细节. Storage contract SimpleSt ...
- 以太坊智能合约Hello World示例程序
简介 以太坊(Ethereum)是一提供个智能合约(smart contract)功能的公共区块链(BlockChain)平台. 本文介绍了一个简单的以太坊智能合约的开发过程. 开发环境 在以太坊上开 ...
- 如何通过以太坊智能合约来进行众筹(ICO)
前面我们有两遍文章写了如何发行代币,今天我们讲一下如何使用代币来公开募资,即编写一个募资合约. 写在前面 本文所讲的代币是使用以太坊智能合约创建,阅读本文前,你应该对以太坊.智能合约有所了解,如果你还 ...
- 深入以太坊智能合约 ABI
开发 DApp 时要调用在区块链上的以太坊智能合约,就需要智能合约的 ABI.本文希望更多了解 ABI,如为什么需要 ABI?如何解读 Ethereum 的智能合约 ABI?以及如何取得合约的 ABI ...
- Go语言打造以太坊智能合约测试框架(level1)
传送门: 柏链项目学院 Go语言打造以太坊智能合约测试框架 前言 这是什么? 这是一个基于go语言编写的,自动化测试以太坊智能合约的开发框架,使用此框架,可以自动化的部署合约,自动测试合约内的功能函数 ...
- rpc接口调用以太坊智能合约
rpc接口调用以太坊智能合约 传送门: 柏链项目学院 在以太坊摸爬滚打有些日子了,也遇到了各种各样的问题.这几天主要研究了一下如何通过rpc接口编译.部署和调用合约.也遇到了一些困难和问题,下面将 ...
- Go语言打造以太坊智能合约测试框架(level3)
传送门: 柏链项目学院 第三课 智能合约自动化测试 之前课程回顾 我们之前介绍了go语言调用exec处理命令行,介绍了toml配置文件的处理,以及awk处理文本文件获得ABI信息.我们的代码算是完成了 ...
- 使用web3.js监听以太坊智能合约event
传送门: 柏链项目学院 使用web3.js监听以太坊智能合约event 当我们在前端页面调用合约时发现有些数据不会立即返回,这时还需要再调用更新数据的函数.那么这样的方法使用起来非常不便,监听ev ...
随机推荐
- IDEA中try/catch快捷键
Ctrl + Alt + t
- Go plan9 汇编: 打通应用到底层的任督二脉
原创文章,欢迎转载,转载请注明出处,谢谢. 0. 前言 作为一个严肃的 Gopher,了解汇编是必须的.本汇编系列文章会围绕基本的 Go 程序介绍汇编的基础知识. 1. Go 程序到汇编 首先看一个简 ...
- C语言指针的作业
指针的作业 求Sn = a + aa + aaa + aaaa + aaaaa的前五项和,其中a是一个数字. 例如:2 + 22 + 222 + 2222 + 22222 /* 求Sn = a + a ...
- Redis、Nginx、SQLite、Elasticsearch等开源软件成功的原因及他们对IT技术人员的启示
引言 这些年在自研产品,对于如何做好产品进行了一些思考.随着开源软件的蓬勃发展,许多开源项目已经成为IT行业的核心组成部分.像Redis.Nginx.SQLite.Elasticsearch这些知名的 ...
- JAVA基础之5-函数式接口的实现
之所以单独把这个列出来,是因为本人被一个源码给震撼了. 所以,本人目的是看看这个震撼实现,并模仿,最后把常规的实现也贴上,让读者可以看到相对完整的实现 注:本文代码基于JDK17 一.让人震撼的代码 ...
- CSS – Float
前言 Float 是上古时代的东西, 它的效果已经基本被 Flex, Grid 取代了. 但是还是可以了解它一下. 就当学习历史呗. 参考 Youtube – HTML & CSS for B ...
- vue3 3.3.4
https://cn.vuejs.org/guide/introduction.html#what-is-vue 简介 import { createApp } from 'vue' createAp ...
- Vue3——SVG 图标配置
1. SVG 图标配置 安装 SVG 依赖插件 vite-plugin-svg-icons npm i vite-plugin-svg-icons -D npm install fast-glob - ...
- 【赵渝强老师】Flink的Watermark机制(基于Flink 1.11.0实现)
在使用eventTime的时候如何处理乱序数据?我们知道,流处理从事件产生,到流经source,再到operator,中间是有一个过程和时间的.虽然大部分情况下,流到operator的数据都是按照事件 ...
- LeetCode 407. 接雨水 II (优先队列)
参考 优先队列的思路解决接雨水II,逐行解释 从最外圈开始不断向内遍历,如果内部的高度小于外部的高度,则证明该位置可以蓄水,否则不能,水会顺着该外圈流出去. 每次都处理外圈高度最小的那个位置 a,遍历 ...