智能合约
jerem1ah Lv4

智能合约入门

0x01-[学习笔记]智能合约

参考题目1:https://github.com/LCTF/LCTF2018/tree/master/Writeup/gg%20bank

参考题目2:https://www.ctfiot.com/111908.html

合约1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
contract ggbank is ggToken{
address public owner;
mapping(uint => bool) locknumber;

event GetFlag(
string b64email,
string back
);

modifier authenticate {
require(checkfriend(msg.sender));_;
}
constructor() public {
owner=msg.sender;
}
function checkfriend(address _addr) internal pure returns (bool success) {
bytes20 addr = bytes20(_addr);
bytes20 id = hex"000000000000000000000000000000000007d7ec";
bytes20 gg = hex"00000000000000000000000000000000000fffff";

for (uint256 i = 0; i < 34; i++) {
if (addr & gg == id) {
return true;
}
gg <<= 4;
id <<= 4;
}

return false;
}
function getAirdrop() public authenticate returns (bool success){
if (!initialized[msg.sender]) {
initialized[msg.sender] = true;
balances[msg.sender] = _airdropAmount;
_totalSupply += _airdropAmount;
}
return true;
}
function goodluck() public payable authenticate returns (bool success) {
require(!locknumber[block.number]);
require(balances[msg.sender]>=100);
balances[msg.sender]-=100;
uint random=uint(keccak256(abi.encodePacked(block.number))) % 100;
if(uint(keccak256(abi.encodePacked(msg.sender))) % 100 == random){
balances[msg.sender]+=20000;
_totalSupply +=20000;
locknumber[block.number] = true;
}
return true;
}


function PayForFlag(string b64email) public payable authenticate returns (bool success){

require (balances[msg.sender] > 200000);
emit GetFlag(b64email, "Get flag!");
}
}

合约2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
pragma solidity 0.8.19;

contract SignIn {
Greeter public greeter;
address public owner;
uint8 private unusal1;
uint256[4] private unusal2;
bytes32 private key;

modifier onlyOwner() {
require(tx.origin == owner);
_;
}

constructor() {
greeter = Greeter(msg.sender);
owner = tx.origin;
key = keccak256(abi.encodePacked(block.timestamp));
}

function getFlag(bytes32 _key) external onlyOwner {
require(_key == key);
greeter.getFlag();
}
}

contract Greeter {
event StartChallenge(address indexed challenge);
event CaptureTheFlag(address indexed player);

mapping(address => bool) SignIn_Deployed;

modifier onlySignIn() {
require(SignIn_Deployed[msg.sender]);
_;
}

constructor() {}

function startChallenge() external returns (address) {
address _SignInAddress = address(new SignIn());
SignIn_Deployed[_SignInAddress] = true;
emit StartChallenge(_SignInAddress);
return _SignInAddress;
}

function getFlag() external onlySignIn {
SignIn_Deployed[msg.sender] = false;
emit CaptureTheFlag(tx.origin);
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
在以太坊合约中,emit 关键字用于触发事件。事件允许合约向外部世界发出信息。
事件的语法如下:
solidity
event EventName(string arg1, address arg2, uint arg3);

function f() public {
emit EventName("hello", msg.sender, 10);
}
我们在合约中定义事件 EventName,携带三个参数;然后在函数 f 中使用 emit EventName(...) 来触发这个事件。
事件具有以下特性:
- 事件在区块链上记录发生过的事情,但事件本身不会改变状态。
- 事件可以被应用前端和其他事件监听器捕获和解析。
- 事件作为区块链上的日志被保留。
- 事件参数可以为复杂类型,但会增加交易的 gas 花费。
- 事件没有重载,同名事件会被后定义的覆盖。
事件主要用于两方面用途:
1. 向用户界面通知状态的变化,让 UI 进行更新。比如在交易执行后触发充值成功事件,让用户界面显示充值完成。
2. 通过事件过滤器监听特定事件。智能合约可以监听其他合约触发的事件,从而执行某些逻辑。
总之,emit 关键字和事件在以太坊智能合约中起到通知和触发作用,它允许合约在状态变化时通知外部世界。这是一种简单高效的跨合约通信方式。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
RPC 全称为 Remote Procedure Call,意为远程过程调用。它是一种进程间通信方式,允许程序调用另一个地址空间(通常是网络的另一台机器上)的过程或函数,而不用程序员显式编码这个远程调用的细节。
以太坊中,RPC 通常指的的是以太坊 JSON-RPC API。这是一个基于 JSON-RPC 2.0 规范的 API,它允许客户端远程调用运行在 Ethereum 节点(如 Geth 或 Parity)上的 RPC 服务器。通过这些调用,客户端可以读取区块链数据、发送交易、部署和调用智能合约等。
例如,要通过 RPC 查询以太坊最新区块高度,可以发送如下请求:
json
{
"jsonrpc": "2.0",
"method": "eth_blockNumber",
"params": [],
"id": 1
}
RPC 服务器会返回如下响应:
json
{
"jsonrpc": "2.0",
"id": 1,
"result": "0x4b7" // 1207
}
其他常用的 RPC 方法还有:
- eth_getBalance:获取地址余额
- eth_sendRawTransaction:发送交易
- eth_getBlockByHash:根据区块哈希获取区块信息
- eth_getTransactionReceipt:获取交易收据
- eth_call:调用智能合约函数
- etc.
总之,RPC 在以太坊生态中广泛使用,它是客户端与全节点进行交互的主要方式之一。藉由这种交互,客户端获得区块链必要的数据并能够修改链状态。

结语小记:上午在装ethereum库python一直装不上pyethash依赖,最后kali上解决。以后装不上的库直接去kali装,方便不少!。

 Comments