solidity基础语法与简单案例20221129

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,只能用于输入的参数中。

需要定义的函数类型包括: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;
    }
}

猜你喜欢

转载自blog.csdn.net/H_Roger/article/details/128095188
今日推荐