// 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"));
}
}
/*
*/
/*
*/
/*
*/
/*
*/
共有 0 条评论