DEV Community

晓道
晓道

Posted on • Edited on

一个蜜罐合约的解析

合约地址在:
etherscan

网上的讨论地址
reddit
源码如下:

contract defi_game {
    function Try(string memory _response) public payable {
        if (
            answerHash == keccak256(abi.encode(_response)) &&
            msg.value > 1 ether
        ) {
            payable(msg.sender).transfer(address(this).balance);
        }
    }

    string public question;

    bytes32 answerHash;

    mapping(bytes32 => bool) admin;

    function Start(string calldata _question, string calldata _response)
        public
        payable
        isAdmin
    {
        if (answerHash == 0x0) {
            answerHash = keccak256(abi.encode(_response));
            question = _question;
        }
    }
    function New(string calldata _question, bytes32 _answerHash) public payable isAdmin {
        question = _question;
        answerHash = _answerHash;
    }
    function Stop() public payable isAdmin {
        payable(msg.sender).transfer(address(this).balance);
    }

    constructor(bytes32[] memory admins) {
        for (uint256 i = 0; i < admins.length; i++) {
            admin[admins[i]] = true;
        }
    }

    modifier isAdmin() {
        require(admin[keccak256(abi.encodePacked(msg.sender))]);
        _;
    }

    fallback() external {}
}
Enter fullscreen mode Exit fullscreen mode

分别是部署合约(constructor),开始游戏(Start),尝试(Try),停止游戏(Stop)
从代码来看,整个代码就是,猜谜游戏,start出题、设置答案,Try解题,对了就转账给对的人。
从交易记录来看,出题人,一下转了2个eth进去,Try需要至少1个eth才能进行。
结果就是合约部署人,在constructor的时候把自己账号的
keccak256(abi.encodePacked(msg.sender)给设置进去

for (uint256 i = 0; i < admins.length; i++) {
            admin[admins[i]] = true;
        }
Enter fullscreen mode Exit fullscreen mode

Start的时候设置问题,

answerHash = keccak256(abi.encode(_response));
question = _question;

这个地方question是一个public变量,所以你能在链上面看到问题,通过Start的参数,你可以看到答案,但是这不是真的答案,
try一下你就知道,try一下就至少一个ETH

本地源码部署,测试

我把合约本地部署了一下,调用参数一样,Try可以成功,套路挺深的。
所以那个源码可能不是真的源码。
反汇编代码还是挺累,所以这个坑,后面有时间再填。
如果自己要部署合约,先这样:

function getadmin() public {
    address addr = address(0x9BEF5148fD530244a14830f4984f2B76BCa0dC58);
    bytes32 kca = keccak256(abi.encodePacked(addr));
    emit log_bytes32(kca);//0x8d3dfe9abb5f4b094c84ab5dc2fa239c318e4985fd30286fff6150ea6963222f
}

await defi_game.deploy(["0x0000000000000000000000000000000000000000000000000000000000000020", "0x0000000000000000000000000000000000000000000000000000000000000002",
"0x8d3dfe9abb5f4b094c84ab5dc2fa239c318e4985fd30286fff6150ea6963222f"])
Enter fullscreen mode Exit fullscreen mode

0x9BEF5148fD530244a14830f4984f2B76BCa0dC58 是 Ganache的默认账号。

只是技术探讨,大家可以交流一下。

后面又反汇编了一下代码,发现代码确实是这个。

经过群友Miller的提醒,感谢Miller,ethscan上面合约调用合约显示是有问题的
这个里可以明确看到,New调用

另一个区块链浏览器
16438669931.png
这样就完整了,我一直当ethscan是什么都能看到的,疑惑了几天,看来分析问题得多看几个区块链浏览器。

所以流程如下:

1,部署合约,
2,调用New设置答案hash
3,开始Start,投入2个eth
4,有人Try,投入至少1个eth
5,Stop 收入,转回自己的钱包。

后续,没讲完的
一个蜜罐合约的解析(二)调用隐藏 | 登链社区 | 深入浅出区块链技术 (learnblockchain.cn)

Top comments (0)