智能合约入门
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装,方便不少!。