LEVEL 14 (GatekeeperTwo):
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
contract GatekeeperTwo {
address public entrant;
modifier gateOne() {
require(msg.sender != tx.origin);
_;
}
modifier gateTwo() {
uint x;
assembly { x := extcodesize(caller()) }
require(x == 0);
_;
}
modifier gateThree(bytes8 _gateKey) {
require(uint64(bytes8(keccak256(abi.encodePacked(msg.sender)))) ^ uint64(_gateKey) == uint64(0) - 1);
_;
}
function enter(bytes8 _gateKey) public gateOne gateTwo gateThree(_gateKey) returns (bool) {
entrant = tx.origin;
return true;
}
}
通关要求
entrant=player
要点
1.tx.origin和msg.sender的区别,这个前面有讲
2.EOA和合约区别,以及extcodesize
3.位计算
^ 异或 两个位相同为0,相异为1
解题思路
gateOne:在自己的合约调用其他合约,则tx.origin和msg.sender就会不一样
gateTwo:正常EOA账号的codesize=0,合约不等于0,但有个例外就是在合约的构造器constructor里代用外部合约,这时是codesize为0的,因为还没初始化完合约。
gateThree:位计算,见下面的代码提示
//gateThree:require(uint64(bytes8(keccak256(abi.encodePacked(msg.sender)))) ^ uint64(_gateKey) == uint64(0) - 1);
//结果再异或下
uint64 gateKey;
unchecked {
gateKey = (uint64(0) - 1) ^
uint64(bytes8(keccak256(abi.encodePacked(address(this)))));
}
ILevel(_runAddress).enter(bytes8(gateKey));
}
Top comments (0)