Solidity8.0-02
2024-10-21 03:03:44
对应崔棉大师 26-40课程
https://www.bilibili.com/video/BV1yS4y1N7yu/?spm_id_from=333.788&vd_source=c81b130b6f8bb3082bdb42226729d69c
部署合约
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7; contract TestContract1{
address public owner = msg.sender; function setOwner(address _owner) public{
require(owner== msg.sender,"not owner");
owner = _owner;
} } contract TestContract2{
address public owner = msg.sender;
uint public value = msg.value;
uint public x;
uint public y;
constructor(uint _x,uint _y){
x = _x;
y = _y;
}
} contract Proxy{
function deploy() public payable returns(address addr){
//强转为address类型 否则报错 不能进行隐式转换
// owner地址为Proxy地址
addr = address(new TestContract1());
return addr;
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
contract Proxy {
event Deploy(address); //事件
fallback() external payable {} //可能接受主币要有回退函数
receive () payable external {} //
function deploy(bytes memory _code) external payable returns (address addr) {
assembly { //内联汇编
// create(v, p, n)
// v = amount of ETH to send 发送eth金额
// p = pointer in memory to start of code 合约二进制编码,再偏移20
// n = size of code 合约二进制编码长度
addr := create(callvalue(), add(_code, 0x20), mload(_code)) //隐式返回
}
// return address 0 on error
require(addr != address(0), "deploy failed"); //确实部署成功返回地址不为0
emit Deploy(addr);
}
function execute(address _target, bytes memory _data) external payable {
//_target目标地址
(bool success, ) = _target.call{value: msg.value}(_data);
require(success, "failed");
}
}
contract TestContract1 {
address public owner = msg.sender;
function setOwner(address _owner) public {
require(msg.sender == owner, "not owner");
owner = _owner;
}
}
contract TestContract2 {
address public owner = msg.sender;
uint public value = msg.value;
uint public x;
uint public y;
constructor(uint _x, uint _y) payable {
x = _x;
y = _y;
}
}
contract Helper {
function getBytecode1() external pure returns (bytes memory) {
bytes memory bytecode = type(TestContract1).creationCode;// 获取二进制编码
return bytecode;
}
function getBytecode2(uint _x, uint _y) external pure returns (bytes memory) {
bytes memory bytecode = type(TestContract2).creationCode;// 获取二进制编码
return abi.encodePacked(bytecode, abi.encode(_x, _y)); //构造函数编码后拼接
}
function getCalldata(address _owner) external pure returns (bytes memory) {
return abi.encodeWithSignature("setOwner(address)", _owner); //构造函数call编码
}
}
存储位置
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
contract DataLocations {
struct MyStruct{
uint foo;
string text;
}
mapping(address => MyStruct) public MyStructs;
function examples(string memory _x,uint[] calldata _y) external{
MyStructs[msg.sender] = MyStruct({foo:123,text:"bar"});
//状态变量
MyStruct storage write = MyStructs[msg.sender];
write.text = "foo";
//局部变量
MyStruct memory read = MyStructs[msg.sender];
read.foo = 456;
//节省gas:calldata传递参数时候不需要重新赋值 memory传递参数需要重新赋值
calldata_fun(_x,_y);
}
function calldata_fun(string memory _x,uint[] calldata _y ) private pure returns(uint,string memory){
uint y = _y[0];
string memory x = _x;
return (y,x);
}
}
简单存储
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
contract SimpleStorage {
string public text;
// transaction cost 27359 gas 交易消耗gas (包括execution cost)
// execution cost 5851 gas evm执行消耗gas
function memory_set(string memory _input) external{
text = _input;
}
// transaction cost 26855 gas
// execution cost 5347 gas
//节省gas:calldata比memory 执行gas少
function calldata_set(string calldata _input) external{
text = _input;
}
}
待办事项列表
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
contract ToDoList {
struct Todo{
string text;
bool completed;
}
Todo[] public todos;
function create(string calldata _text) external{
todos.push(Todo({
text:_text,
completed:false
}));
}
function updateText(uint _index,string calldata _text) external{
//节省gas:单个参数更新下面的方式
todos[_index].text = _text;
// 节省gas:多个参数更新下面的方式
// Todo storage t = todos[_index];
// t.text = "a";
// t.text = "b";
// t.text = "c";
// t.text = "d";
}
function get(uint _index) external view returns(string memory,bool){
//从storage到return复制一次
//Todo storage todo = todos[_index];
//storage到memory到memory 复制两次
Todo memory todo = todos[_index];
return (todo.text,todo.completed);
}
function toggleCompleted(uint _index) external {
todos[_index].completed = !todos[_index].completed;
}
}
事件
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
contract Event {
// Event declaration
// Up to 3 parameters can be indexed. 一个时间最多定义三个索引
// Indexed parameters helps you filter the logs by the indexed parameter
event Log(address indexed sender, string message);
event AnotherLog();
function test() public {
emit Log(msg.sender, "Hello World!");
emit Log(msg.sender, "Hello EVM!");
emit AnotherLog();
}
}
继承
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
contract A {
function foo() public pure virtual returns (string memory) {
return "A";
}
function bar() public pure virtual returns (string memory) {
return "A";
}
function barz() public pure virtual returns (string memory) {
return "A";
}
}
// Contracts inherit other contracts by using the keyword 'is'.
contract B is A {
// Override A.foo()
function foo() public pure virtual override returns (string memory) {
return "B";
}
function bar() public pure virtual override returns (string memory) {
return "B";
}
}
contract C is B {
// Override A.foo()
function bar() public pure virtual override returns (string memory) {
return "C";
}
}
多线继承
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
// X
// / \
// Y \
// \ /
// Z
contract X {
function foo() public pure virtual returns (string memory) {
return "X";
}
function bar() public pure virtual returns (string memory) {
return "X";
}
function _X() public pure returns (string memory) {
return "X";
}
}
// Contracts inherit other contracts by using the keyword 'is'.
contract Y is X {
// Override A.foo()
function foo() public pure virtual override returns (string memory) {
return "Y";
}
function bar() public pure virtual override returns (string memory) {
return "Y";
}
function _Y() public pure returns (string memory) {
return "Y";
}
}
//按基类和派生顺序继承
contract Z is X,Y {
// Override A.foo()
function bar() public pure virtual override(X,Y) returns (string memory) {
return "Z";
}
function foo() public pure virtual override(X,Y) returns (string memory) {
return "Z";
}
function _Z() public pure returns (string memory) {
return "Z";
}
}
运行父级合约构造函数
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
contract S {
string public text;
constructor(string memory _text){
text = _text;
}
}
contract T {
string public name;
constructor(string memory _name){
name = _name;
}
}
//已知构造函数
contract V is S("s"),T("t") {
}
//未知构造函数
contract VV is S,T {
constructor(string memory _text,string memory _name) S(_text) T(_name){
}
}
//混合使用
contract VVV is S("s"),T {
constructor(string memory _name) T(_name){
}
}
调用父级合约函数
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
/* Inheritance tree
A
/ \
B C
\ /
D
*/
contract A {
event Log(string message);
function foo() public virtual {
emit Log("A.foo called");
}
function bar() public virtual {
emit Log("A.bar called");
}
}
contract B is A {
function foo() public virtual override {
emit Log("B.foo called");
//第一种调用方式
A.foo();
}
function bar() public virtual override {
emit Log("B.bar called");
//第二种调用方式
super.bar();
}
}
contract C is A {
function foo() public virtual override {
emit Log("C.foo called");
A.foo();
}
function bar() public virtual override {
emit Log("C.bar called");
super.bar();
}
}
//当 B , C 到基类长度相等时,只调用最后面的B
contract D is C,B {
// Try:
// - Call D.foo and check the transaction logs.
// Although D inherits A, B and C, it only called C and then A.
// - Call D.bar and check the transaction logs
// D called C, then B, and finally A.
// Although super was called twice (by B and C) it only called A once.
function foo() public override(B, C) {
super.foo();
}
function bar() public override(B, C) {
super.bar();
}
}
可视范围
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
contract VisibilityBase{
uint private x;
uint internal y;
uint public z;
function privateFunc() private pure returns(uint){
}
function internalFunc() internal pure returns(uint){
}
function publicFunc() public pure returns(uint){
}
function externalFunc() external pure returns(uint){
}
function examples() public view returns(uint res){
res = x + y + z;
privateFunc();
internalFunc();
publicFunc();
//先到外部再call
this.externalFunc();
}
}
不可变量
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
contract Immutable {
// 节省gas:但是必须在部署合约时赋值
address public immutable MY_ADDRESS;
uint public immutable MY_UINT;
constructor(uint _myUint) {
MY_ADDRESS = msg.sender;
MY_UINT = _myUint;
}
}
支付ETH
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
contract Payable {
/*地址有两种类型
address
payable address 多了两个成员方法send和transfer
send方法相比较transfer方法来说更“底层”一些,如果send方法执行失败,并不会抛出异常,而是返回false。
*/
address payable public owner;
// 普通address需要强转payable address
constructor() payable {
owner = payable(msg.sender);
}
function deposit() public payable {}
function getBalance() public view returns(uint){
return address(this).balance;
}
}
回退函数
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
contract Fallback {
event Log(string message,uint gas);
/* fallback() or receive() ?
ETH Send
|
msg.data is empty?
/ \
/ \
yes no
| |
receive() exists? fallback()
/ \
/ \
yes no
| |
receive() fallback()
*/
fallback() external payable {
emit Log("fallback()",gasleft());
}
receive() external payable {
emit Log("receive()",gasleft());
}
// Helper function to check the balance of this contract
function getBalance() public view returns (uint) {
return address(this).balance;
}
}
contract SendToFallback {
function transferToFallback(address payable _to) public payable {
_to.transfer(msg.value);
}
function callFallback(address payable _to) public payable {
(bool sent, ) = _to.call{value: msg.value}("123");
require(sent, "Failed to send Ether");
}
}
发送ETH
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
contract ReceiveEther {
event Log(uint amount,uint gas);
receive() external payable {
emit Log(msg.value,gasleft());
}
}
contract SendEther {
event Log(bool sent);
function sendViaTransfer(address payable _to) public payable {
// This function is no longer recommended for sending Ether.
_to.transfer(msg.value);
}
function sendViaSend(address payable _to) public payable {
// Send returns a boolean value indicating success or failure.
// This function is not recommended for sending Ether.
bool sent = _to.send(msg.value);
emit Log(sent);
require(sent, "Failed to send Ether");
}
function sendViaCall(address payable _to) public payable {
// Call returns a boolean value indicating success or failure.
// This is the current recommended method to use.
(bool sent, bytes memory data) = _to.call{value: msg.value,gas:222222}("");
require(sent, "Failed to send Ether");
}
}
钱包合约
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
contract EtherWallet {
address payable public owner;
constructor() {
owner = payable(msg.sender);
}
receive() external payable {}
function withdraw(uint _amount) external {
require(msg.sender == owner, "caller is not owner");
payable(msg.sender).transfer(_amount);
}
function getBalance() external view returns (uint) {
return address(this).balance;
}
}
最新文章
- C#6.0 十大常用特性
- JavaScript下的setTimeout(fn,0)意味着什么?
- 【DP】HIHO 1078
- HTML的基本代码第一课
- nested exception is java.lang.RuntimeException: Error parsing Mapper XML. Cause: java.lang.IllegalArgumentException: Result Maps collection already contains value for
- php报错日志:PHP Deprecated:Automatically populating $HTTP_RAW_POST_DATA is deprecated
- CUDA学习笔记(三)——CUDA内存
- BZOJ_1614_ [Usaco2007_Jan]_Telephone_Lines_架设电话线_(二分+最短路_Dijkstra/Spfa)
- Linux各种包安装及命令
- 正则表达式之match与exec【转的 楼兰之风】
- 老旧Webkit浏览器行内元素0间距问题
- C--运算符,表达式和语句实例
- extjs中,datefield日期,点击输入框弹出日期,禁止手动输入
- Java原子类中CAS的底层实现
- Linux系统下配置网络、JAVA环境,配置tomcat,mysql
- LeetCode算法题-Second Minimum Node In a Binary Tree(Java实现)
- sizeof和strlen()区别及用法
- 微信中H5网页如何唤醒打开外部浏览器打开指定链接
- 在Spring(4.3.22)中集成Hibernate(5.4.0)
- cp命令覆盖文件时不用按Y来确认的方法
热门文章
- Linux下“减速”查看日志的方法
- 【转载】EXCEL VBA 自定义排序的三种方法
- 深入理解 Linux 物理内存分配全链路实现
- JavaScript 中如何拦截全局 Fetch API 的请求和响应?
- UnoCSS 简化 CSS 的书写,Nice!
- Blazor WebAssembly的初次访问慢的优化
- 【Vue3.0】关于 script setup 语法糖的用法
- 第 1 天|基于 AI 进行游戏开发:5 天创建一个农场游戏!
- ChatGPT保姆级注册教程
- C#DataTable(转List /JSON/字典 互转)