1、映射
// SPDX-License-Identifier:MIT
pragma solidity ^0.8.7; //定义solidity版本号
contract map {
mapping(address => uint) public balances; //构建地址对账户余额的映射
mapping(address => bool) public inserted; //构建地址是否已插入的映射
address[] public keys; //构建合约地址数组
function set(address _key,uint _val) external{ //为账户映射设定数值
balances[_key] = _val;
if(!inserted[_key]){
inserted[_key] = true;
keys.push(_key);
}
}
function gesSize() external view returns (uint){
return keys.length;
}
function first() external view returns(uint){
return balances[keys[0]];
}
function last() external view returns(uint){
return balances[keys[keys.length - 1]];
}
}
2、结构体
用于自定义数据类型
// SPDX-License-Identifier:MIT
pragma solidity ^0.8.7;
contract Struct{
struct Car{
string name;
uint year;
address Owner;
}
Car public car;
Car[] public cars;
mapping(address => Car[]) public carsByowner; //构建一个映射,用于查询所有者拥有的车
function example(string memory _name,uint _year) external{
cars.push(Car(_name,_year,msg.sender));
carsByowner[msg.sender] = cars;
}
}
3、使用代理合约部署合约
通过输入需要部署的合约的机器码,实现利用合约部署合约。
包含一个部署合约和一个帮助合约(用于生成机器码)。
// SPDX-License-Identifier:MIT
pragma solidity ^0.8.7;
contract TestContract1{
address public owner = msg.sender;
function setOwner(address _owner) public{
require(msg.sender == owner,"notOnwer");
owner = _owner;
}
}
//与测试合约1的差异:具有构造函数
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 Proxy {
event Deploy(address);
fallback() external payable{}//由于合约包含payable关键词,需要添加回退函数
constructor() payable{}
function deploy(bytes memory _code) external payable returns (address addr){
assembly{
//callvalue:本次部署过程中,部署者发送的主币,=msg.value
//add(_code,0x20),code内容及位置,可以视为固定语法
//mload(_code) code的长度
//addr:create方法返回的部署地址
addr := create(callvalue(),add(_code,0x20),mload(_code))
}
//要求部署合约地址不能为0地址,如果是则认定为失败
require(addr != address(0),"deploy failed");
//触发事件,形成记录
emit Deploy(addr);
}
//合约1只能由合约的部署者调用,因此需要加入新的内容实现利用母合约控制部署合约
function execute(address _target,bytes memory _data) external payable {
(bool success, ) = _target.call{value:msg.value}(_data);
require(success,"failed");
}
}
//形成构建合约所需要的机器码,包括合约1,合约2.
//合约2包含构造函数,构造函数实际上是连接在机器码后面的一串16进制数字。
contract Helper {
function getBytecode1() external pure returns (bytes memory) {
//将测试合约1变成机器码
bytes memory bytecode = type(TestContract1).creationCode;
return bytecode;
}
function getBytecode2(uint _x,uint _y) external pure returns (bytes memory) {
//将测试合约2变成机器码
bytes memory bytecode = type(TestContract1).creationCode;
//将机器码和输入的构造函数数值进行打包
return abi.encodePacked(bytecode,abi.encode(_x,_y));
}
function getCalldata(address _owner) external pure returns (bytes memory){
//使用代理合约调用setOwner()方法,并输入owner参数
return abi.encodeWithSignature("setOwner(address)",_owner);
}
}
4、数据的储存位置
在solidity中,数据的存储位置可以以storage、memory和calldata三种修饰词进行定义。
storage:存储在链上,在结束运行后数据保存在链上。
memory:存储在内存中,结束运行后数据消失。
calldata:用于节约gas,只能用于输入的参数中。
扫描二维码关注公众号,回复:
15381258 查看本文章
需要定义的函数类型包括:string、struct和数组。
// SPDX-License-Identifier:MIT
pragma solidity ^0.8.7;
contract DataLocation {
struct MyStruct{
uint num;
string text;
}
mapping(address => MyStruct) public myStructs;
function get_struct_storage() external{
//构建一个num为123且text为“aaa”的MyStruct,并且与function调用者的地址进行mapping
myStructs[msg.sender] = MyStruct({num:123,text:"aaa"});
}
//calldata只能在传参的时候使用,可以将输入的参数直接传递至下一个function中,从而减少gas量
function change_Struct_text(uint[] calldata y, string calldata s) external returns(uint[] memory){
//将变量读取出来,并使用storage作为存储位置,此时,对链上数据进行修改
MyStruct storage myStruct = myStructs[msg.sender];
myStruct.text = "bbb";
//局部变量,并不能修改链上数据
MyStruct memory readOnly = myStructs[msg.sender];
readOnly.text = "bbb";
}
function _internal(uint[] calldata y) private{
uint x = y[0];
}
function read_Struct() public view returns(string memory){
//读取数据
MyStruct storage myStruct = myStructs[msg.sender];
return myStruct.text;
}
}
5、简单回顾:SimpleStorage
external外部可见意味着合约内其他函数不能调用
// SPDX-License-Identifier:MIT
pragma solidity ^0.8.7;
contract SimpleStorage{
string public text;
function set(string calldata _text) external {
text = _text;
}
function get() external view returns(string memory){
return text;
}
}