电商网站开发开题报告,网站和网络有什么区别,对网站建设的评价,云南建设厅官方网站我一度觉得自己不知何时变成了一个浮躁的人#xff0c;一度不想受外界干扰的我被干扰了#xff0c;再无法平静的去看一本书#xff0c;但我仍旧希望我能够克服这些#xff0c;压抑着自己直到所有的冲动和奇怪的思想都无法再左右我行动。 自律会让你更加自律#xff0c;放纵…我一度觉得自己不知何时变成了一个浮躁的人一度不想受外界干扰的我被干扰了再无法平静的去看一本书但我仍旧希望我能够克服这些压抑着自己直到所有的冲动和奇怪的思想都无法再左右我行动。 自律会让你更加自律放纵会让你更加放纵。 做人做事都是如此。 简单的道理却要克服很多东西。做正确的事情而不是我想做的事情。发乎情止乎理。
速成班
1全世界人们入门的统一标准hello world
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.21;
contract HelloWeb3{string public _string Hello Web3!;
}前两行类似于说明文件contract说明你开始编写一个合约这个合约的名字叫做helloweb3,合约内声明了一个字符串public _string叫做 “Hello Web3!” 这个hello world我编译失败了 莫名其妙又成功了把编译的篮子放在了右边就成功了
2 值类型
bool类型
// 声明一个对外可访问的bool
bool public _bool true;// 布尔运算
bool public _bool1 !_bool; // 取非
bool public _bool2 _bool _bool1; // 与
bool public _bool3 _bool || _bool1; // 或
bool public _bool4 _bool _bool1; // 相等
bool public _bool5 _bool ! _bool1; // 不相等整型
// 整型
int public _int -1; // 整数包括负数
uint public _uint 1; // 正整数
uint256 public _number 20220330; // 256位正整数// 整数运算
uint256 public _number1 _number 1; // -*/
uint256 public _number2 2**2; // 指数
uint256 public _number3 7 % 2; // 取余数
bool public _numberbool _number2 _number3; // 比大小地址类型
地址类型(address)有两类 普通地址address: 存储一个 20 字节的值以太坊地址的大小。 payable address: 比普通地址多了 transfer 和 send 两个成员方法用于接收转账。
// 地址
address public _address 0x7A58c0Be72BE218B41C608b7Fe7C5bB630736C71;
address payable public _address1 payable(_address); // payable address可以转账、查余额
// 地址类型的成员
uint256 public balance _address1.balance; // balance of address我有点不是太理解这个payable address
定长字节数组
// 固定长度的字节数组
bytes32 public _byte32 MiniSolidity;
bytes1 public _byte _byte32[0]; 32个字节组成的数组也就是可以容纳32个元素很明显后面的并没有使用u8类型就是32个数字hex 64类型就是32的元素组成的数组0-f
枚举enum
// 用enum将uint 0 1 2表示为Buy, Hold, Sell
enum ActionSet { Buy, Hold, Sell }
// 创建enum变量 action
ActionSet action ActionSet.Buy;枚举的使用方法和各种语言的枚举方式几乎是相同的。 但是这段代码我有点没看明白。
// enum可以和uint显式的转换
function enumToUint() external view returns(uint){return uint(action);
}在 Solidity 中external 是一个函数修饰符用于定义函数的可见性。函数的可见性决定了函数可以从哪里被调用。也就是external和public其实是同级的。
3函数function
function function name(parameter types) {internal|external|public|private} [pure|view|payable] [returns (return types)]看着有一些复杂让我们从前往后逐个解释(方括号中的是可写可不 写的关键字)
function声明函数时的固定用法。要编写函数就需要以 function 关键字开头。
函数名。
()圆括号内写入函数的参数即输入到函数的变量类型和名称。
{internal|external|public|private}函数可见性说明符共有4种。
public内部和外部均可见。 private只能从本合约内部访问继承的合约也不能使用。 external只能从合约外部访问但内部可以通过 this.f() 来调用f是函数名。 internal: 只能从合约内部访问继承的合约可以用。 注意 1合约中定义的函数需要明确指定可见性它们没有默认值。
注意 2public|private|internal 也可用于修饰状态变量。public变量会自动生成同名的getter函数用于查询数值。未标明可见性类型的状态变量默认为internal。
[pure|view|payable]决定函数权限/功能的关键字。payable可支付的很好理解带着它的函数运行的时候可以给合约转入 ETH。pure 和 view 的介绍见下一节。
[returns ()]函数返回的变量类型和名称。
有关于pure 和view
刚开始学习 solidity 时pure 和 view 关键字可能令人费解因为其他编程语言中没有类似的关键字。solidity 引入这两个关键字主要是因为 以太坊交易需要支付气费gas fee。合约的状态变量存储在链上gas fee 很贵如果计算不改变链上状态就可以不用付 gas。包含 pure 和 view 关键字的函数是不改写链上状态的因此用户直接调用它们是不需要付 gas 的注意合约中非 pure/view 函数调用 pure/view 函数时需要付gas。
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.21;
contract FunctionTypes{uint256 public number 5;constructor() payable {}// 函数类型// function (parameter types) {internal|external} [pure|view|payable] [returns (return types)]// 默认functionfunction add() external{number number 1;}// pure: 纯纯牛马// 没有读取权因此什么东西都是别人传给他的// 瞎子function addPure(uint256 _number) external pure returns(uint256 new_number){new_number _number1;}// view: 看客function addView() external view returns(uint256 new_number) {new_number number 1;}// internal: 内部函数function minus() internal {number number - 1;}// 合约内的函数可以调用内部函数function minusCall() external {minus();}// payable: 递钱能给合约支付eth的函数function minusPayable() external payable returns(uint256 balance) {minus(); balance address(this).balance;}
}
internal和external
internal是只可以被内部调用的函数方法external是可以被外部调用的。
4函数return
返回值return 和 returns
Solidity 中与函数输出相关的有两个关键字return和returns。它们的区别在于
returns跟在函数名后面用于声明返回的变量类型及变量名。 return用于函数主体中返回指定的变量。
// 返回多个变量
function returnMultiple() public pure returns(uint256, bool, uint256[3] memory){return(1, true, [uint256(1),2,5]);
}这里uint256[3]声明了一个长度为3且类型为uint256的数组作为返回值。因为[1,2,3]会默认为uint8(3)因此[uint256(1),2,5]中首个元素必须强转uint256来声明该数组内的元素皆为此类型。数组类型返回值默认必须用memory修饰。 我有点没看明白这个memory 和rust有一个类似的地方可以不接受不需要的参数
(, _bool2, ) returnNamed();5函数存储和作用域
引用类型包括数组array和结构体struct由于这类变量比较复杂占用存储空间大我们在使用时必须要声明数据存储的位置。
Solidity数据存储位置有三类storagememory和calldata。不同存储位置的gas成本不同。storage类型的数据存在链上类似计算机的硬盘消耗gas多memory和calldata类型的临时存在内存里消耗gas少。大致用法 storage合约里的状态变量默认都是storage存储在链上。 memory函数里的参数和临时变量一般用memory存储在内存中不上链。尤其是如果返回数据类型是变长的情况下必须加memory修饰例如string, bytes, array和自定义结构。 calldata和memory类似存储在内存中不上链。与memory的不同点在于calldata变量不能修改immutable一般用于函数的参数。
我的感觉就是calldata是栈数据虽然不知道为什么不可变然后memory就类似于堆数据的可变数据
function fCalldata(uint[] calldata _x) public pure returns(uint[] calldata){//参数为calldata数组不能被修改// _x[0] 0 //这样修改会报错return(_x);
}变量的作用域
合约里定义的变量就是所谓的状态变量修改这些状态变量是昂贵的
contract Variables {uint public x 1;uint public y;string public z;function bar() external pure returns(uint){uint xx 1;uint yy 3;uint zz xx yy;return(zz);
}
}全局变量是全局范围工作的变量都是solidity预留关键字。他们可以在函数内不声明直接使用
function global() external view returns(address, uint, bytes memory){address sender msg.sender;uint blockNum block.number;bytes memory data msg.data;return(sender, blockNum, data);
}例子里我们使用了3个常用的全局变量msg.senderblock.number和msg.data他们分别代表请求发起地址当前区块高度和请求数据。
以太单位
Solidity中不存在小数点以0代替为小数点来确保交易的精确度并且防止精度的损失利用以太单位可以避免误算的问题方便程序员在合约中处理货币交易。 wei: 1 gwei: 1e9 1000000000 ether: 1e18 1000000000000000000
function weiUnit() external pure returns(uint) {assert(1 wei 1e0);assert(1 wei 1);return 1 wei;
}function gweiUnit() external pure returns(uint) {assert(1 gwei 1e9);assert(1 gwei 1000000000);return 1 gwei;
}function etherUnit() external pure returns(uint) {assert(1 ether 1e18);assert(1 ether 1000000000000000000);return 1 ether;
}6引用类型 数组和结构体
这里不是很难但是我不是很理解这个memory的array和正常的到底有啥子区别?
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.21;
contract ArrayTypes {// 固定长度 Arrayuint[8] array1;bytes1[5] array2;address[100] array3;// 可变长度 Arrayuint[] array4;bytes1[] array5;address[] array6;bytes array7;// 初始化可变长度 Arrayuint[] array8 new uint[](5);bytes array9 new bytes(9);// 给可变长度数组赋值function initArray() external pure returns(uint[] memory){uint[] memory x new uint[](3);x[0] 1;x[1] 3;x[2] 4;return(x);} function arrayPush() public returns(uint[] memory){uint[2] memory a [uint(1),2];array4 a;array4.push(3);return array4;}
}pragma solidity ^0.8.21;
contract StructTypes {// 结构体 Structstruct Student{uint256 id;uint256 score; }Student student; // 初始一个student结构体// 给结构体赋值// 方法1:在函数中创建一个storage的struct引用function initStudent1() external{Student storage _student student; // assign a copy of student_student.id 11;_student.score 100;}// 方法2:直接引用状态变量的structfunction initStudent2() external{student.id 1;student.score 80;}// 方法3:构造函数式function initStudent3() external {student Student(3, 90);}// 方法4:key valuefunction initStudent4() external {student Student({id: 4, score: 60});}
}pragma solidity ^0.8.21;
contract EnumTypes {// 将uint 0 1 2表示为Buy, Hold, Sellenum ActionSet { Buy, Hold, Sell }// 创建enum变量 actionActionSet action ActionSet.Buy;// enum可以和uint显式的转换function enumToUint() external view returns(uint){return uint(action);}
}7映射 hash
// 这样可以声明一个hashmap
mapping(uint address) public idToAddress; // id映射到地址
mapping(address address) public swapPair; // 币对的映射地址到地址
// 如果希望使用这个map
value idToAddress[key]
// 如果希望添加一个数据
idToAddress[key1] value8初始化变量值
bool public _bool; // false
string public _string; //
int public _int; // 0
uint public _uint; // 0
address public _address; // 0x0000000000000000000000000000000000000000enum ActionSet { Buy, Hold, Sell}
ActionSet public _enum; // 第1个内容Buy的索引0function fi() internal{} // internal空白函数
function fe() external{} // external空白函数 // delete操作符
bool public _bool2 true;
function d() external {delete _bool2; // delete 会让_bool2变为默认值false
}9常数constant和immutable
// constant变量必须在声明的时候初始化之后不能改变
uint256 constant CONSTANT_NUM 10;
string constant CONSTANT_STRING 0xAA;
bytes constant CONSTANT_BYTES WTF;
address constant CONSTANT_ADDRESS 0x0000000000000000000000000000000000000000;// immutable变量可以在constructor里初始化之后不能改变
uint256 public immutable IMMUTABLE_NUM 9999999999;
// 在Solidity v8.0.21以后,下列变量数值暂为初始值
address public immutable IMMUTABLE_ADDRESS;
uint256 public immutable IMMUTABLE_BLOCK;
uint256 public immutable IMMUTABLE_TEST;构造函数和修饰器
构造函数每个合约只能定义一个我认为这个就类似rust里的懒加载lazy_Static用来初始化一些合约的参数。
address owner; // 定义owner变量// 构造函数
constructor(address initialOwner) {owner initialOwner; // 在部署合约的时候将owner设置为传入的initialOwner地址
}看看完全的代码
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.21;contract Owner {address public owner; // 定义owner变量// 构造函数constructor(address initialOwner) {owner initialOwner; // 在部署合约的时候将owner设置为传入的initialOwner地址}// 定义modifiermodifier onlyOwner {require(msg.sender owner); // 检查调用者是否为owner地址_; // 如果是的话继续运行函数主体否则报错并revert交易}// 定义一个带onlyOwner修饰符的函数function changeOwner(address _newOwner) external onlyOwner{owner _newOwner; // 只有owner地址运行这个函数并改变owner}
}筑基期
首先看一个存储合约示例
// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.4.16 0.9.0;contract SimpleStorage {uint storedData;function set(uint x) public {storedData x;}function get() public view returns (uint) {return storedData;}
}第一行告诉您源代码是根据GPL3.0版本授权的。 在发布源代码是默认的情况下机器可读的许可证说明是很重要的。 下一行指定源代码是为Solidity 0.4.16版本编写的或该语言的较新版本直到但不包括0.9.0版本。 这是为了确保合约不能被新的有重大改变的编译器版本编译在那里它可能会有不同的表现。 Pragmas 是编译器关于如何处理源代码的常用指令 例如 pragma once 。 这两行类似于配置contract就类似于结构体或者类了。 我们在类中定义了一个unit数据并设置了set和get函数来获取这个值。我一度很好奇这个view同时这个public 放置的位置也很让我疑惑。搜索后发现
public 关键字用于声明智能合约的状态变量。当一个状态变量被声明为 public 时
它会自动生成一个同名的getter函数允许外部访问这个状态变量的值。
此外public 状态变量的值会被存储在区块链上并且可以通过合约的接口进行访问。
view 关键字用于修饰智能合约的函数。一个被标记为 view 的函数表示这个函数不会修改区块链上的任何状态
它只用于读取数据。调用这样的函数不会产生交易也就是说
它不会消耗gas以太坊网络的费用因为它不会引起状态变化。这使得 view 函数非常适合用于查询操作。我目前把这个public理解为普遍的public因为我不知道他在智能合约里起到一个什么样的作用。
该合约能完成的事情并不多由于以太坊构建的基础架构的原因 它能允许任何人在合约中存储一个单独的数字并且这个数字可以被世界上任何人访问 且没有可行的办法阻止您发布这个数字。 当然任何人都可以再次调用 set 传入不同的值覆盖您的数字 但是这个数字仍会被存储在区块链的历史记录中。 神奇之处来了修改的历史居然会被保存。
接下来我们继续看下一个例子
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.4;contract Coin {// 关键字 public 使变量可以从其他合约中访问。address public minter;mapping(address uint) public balances;// 事件允许客户端对您声明的特定合约变化做出反应event Sent(address from, address to, uint amount);// 构造函数代码只有在合约创建时运行constructor() {minter msg.sender;}// 向一个地址发送一定数量的新创建的代币// 但只能由合约创建者调用function mint(address receiver, uint amount) public {require(msg.sender minter);balances[receiver] amount;}// 错误类型变量允许您提供关于操作失败原因的信息。// 它们会返回给函数的调用者。error InsufficientBalance(uint requested, uint available);// 从任何调用者那里发送一定数量的代币到一个地址function send(address receiver, uint amount) public {if (amount balances[msg.sender])revert InsufficientBalance({requested: amount,available: balances[msg.sender]});balances[msg.sender] - amount;balances[receiver] amount;emit Sent(msg.sender, receiver, amount);}
}address public minter; 这一行声明了一个可以被公开访问的 address 类型的状态变量。 address 类型是一个160位的值且不允许任何算数操作。 这种类型适合存储合约地址或 外部账户 的密钥对。