solidity进阶汇总

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

/*
    全局变量(区块和交易的属性)
        * 常用:
            block.timestamp(uint)  当前块时间戳
            tx.origin(address)  交易的原始发送者的地址,只能是EOA。
            msg.sender(address)  当前调用发起人的地址,可能是合约CA,也可能是EOA
            msg.sig(bytes4)  调用数据的前四个字节(函数标识符)
            msg.value(uint)  这个消息所附带的货币量,单位为wei
            msg.data(bytes)  完整的调用数据,calldata

        * 一般:
            blockhash(bytes32)  哈希值
            block.coinbase(address)  当前块矿工的地址
            block.difficulty(uint)  当前块的难度
            block.gaslimit(uint)  当前块的gaslimit
            block.number(uint)  当前块的块号
            gasleft(uint)  当前还剩的gas
            tx.gasprice(uint)  交易的gas价格

        ps:
            EOA: Externally Owned Account,与一个私钥一一对应,例如小狐狸里面的Account1就是EOA。
            CA: Contract Account,合约账户,没有私钥与之赌赢,部署的合约就是一个CA,它也可以持有资金。  
*/




/*
    msg三剑客(当用户发起一笔交易时,相当于向合约发送一个消息msg,这笔交易可能会涉及到三个重要的变量)
        * msg.sender  表示这笔交易的调用者是谁(地址),同一个交易,不同的用户调用,msg.sender不同。
        * msg.value   表示调用这笔交易时,携带ether数量,这些以太坊由msg.sender支付,转入到当前合约(wei单位整数);
                         注意: 一个函数(或地址)如果想接收ether,需要将其修饰为 ”payable“
        * msg.data    表示调用这笔交易的信息,由函数签名和函数参数(16进制字符串),组成代理模式时常用msg.data。
*/ 
contract MsgSender {
    address public owner;
    uint256 public value;
    address public caller;

    constructor () {
        // 在部署合约的时候,设置一个全局唯一的合约所有者,后续可以用于权限控制;
        owner = msg.sender;
    }

    // 1、对与合约而言,msg.sender 是一个可以改变的值,并不一定是合约的创造者;
    // 2、任何人调用合约的方法,那么这笔交易中的from就是当前合约中的msg.sender;
    function setValue(uint256 input) public {
        value = input;
        caller = msg.sender;
    }
}

contract MsgValue{
    mapping(address => uint256) public personToMoney;

    function play() public payable {
        // 因为这里做转账操作,所以需要使用payable
        require(msg.value == 100, "should equal to 100 wei!");
        personToMoney[msg.sender] = msg.value;
    }

    function getBalance() public view returns(uint256){
        // 代表合约对象本身,可以通过 address(this) 获取合约地址。
        return address(this).balance;
    }
}


contract MsgData {
    event Data(bytes data, bytes4 sig, address addr, uint256 amt);
    
    function transfer(address addr, uint256 amt) public {
        bytes memory data = msg.data;

        // msg.sig 表示当前方法函数签名(4字节)
        // msg.sig 等价于 this.transfer.selector
        emit Data(data, msg.sig, addr, amt);
    }

}


/*
    payable 
        1.一个函数(或地址)如果想接收ether,需要将其修饰为:payable
        2.address常用的方法:
            1)balance: 查询当前地址的ether余额
            2)transfer(uint): 合约向当前地址转指定数量的ether,如果失败会回滚。
            3)send(uint): 合约向当前地址转指定数量的ether,如果失败会返回false,不回滚(不建议使用send)
*/
contract Payable {
    // payable address can receive Ether
    address payable public owner;

    // payable constructor can receive Ether
    constructor() payable {
        owner = payable(msg.sender);
    }

    // function to deposit Ether into this contract 
    function deposit() public payable {}

    // Call this function along wiht some Ether
    // The function will throw an error since this function is not payable.
    function notPayable() public {}

    // function to withdraw all Ether from this contract 
    function withdraw() public {
        // 将合约中的钱存入当前调用合约的地址中
        uint amount = address(this).balance;
        // owner对象调用transfer会将对象当做第一个参数传给transfer方法
        owner.transfer(amount);
    }

    function transfer(address payable _to, uint _amount) public {
        _to.transfer(_amount);
    }
}




/*
    abi.encode: 可以将data编码成bytes,生成bytes总是32字节的倍数,不足32为自动填充(用于给合约调用)。
    abi.decode: 可以将bytes解码成data(可以只解析部分字段)。
    abi.encodePacked: 与abi.encode类似,但是生成的bytes是压缩过的(有些类型不会自动填充,无法传递给合约调用)。

    手册: https://docs.soliditylang.org/en/v0.8.13/abi-spec.html?highlight=abi.encodePacked#non-standard-packed-mode
*/
contract AbiDecode {
    struct MyStruct {
        string name;
        uint[2] nums;
    }

    function encode(uint x, address addr, uint[] calldata arr, MyStruct calldata myStruct) external pure returns (bytes memory) {
        return abi.encode(x, addr, arr, myStruct);
    }

    function decode(bytes calldata data) external pure returns(uint x, address addr, uint[] memory arr, MyStruct memory myStruct) {
        (x, addr, arr, myStruct) = abi.decode(data, (uint, address, uint[], MyStruct));
    }

    function decodeLess(bytes calldata data) external pure returns(uint x, address addr, uint[] memory arr, MyStruct memory myStruct){
        (x) = abi.decode(data, (uint));
    }

    function encodePacked(
        int16 x,
        bytes1 y,
        uint16 z,
        string memory s
    ) external view returns (bytes memory) {

        // encodePacked 不支持struct和mapping
        return abi.encodePacked(x, y, z, s);
    }

      // 可以用encodePacked来拼接字符串
      // output string: ipfs://bafybeidmrsvehl4ehipm5qqvgegi33r6/100.json
      function encodePackedTest() public  pure returns (string memory) {
        string memory uri = "ipfs://bafybeidmrsvehl4ehipm5qqvgegi33r6/";
        return string(abi.encodePacked(uri, "100", ".json"));
    }
    
}





/*

*/




/*

*/




/*

*/




/*

*/

版权声明:
作者:congcong
链接:https://www.techfm.club/p/71910.html
来源:TechFM
文章版权归作者所有,未经允许请勿转载。

THE END
分享
二维码
< <上一篇
下一篇>>