This challenge leverages a staking contract for a token, which inherits functionalities from two critical contracts: Multicall
and ERC2771Context
. Multicall
facilitates the execution of multiple contract calls within a single transaction, enhancing transaction efficiency. Concurrently, ERC2771Context
introduces the concept of meta-transactions, thereby enabling relayers to submit transactions on behalf of users, with the added benefit of relayers covering the associated gas fees.
A pivotal vulnerability, as detailed in this blog post, arises from the exploitable delegatecall
feature found within Multicall
. This feature can be manipulated to alter the resolution of _msgSender()
in subsequent calls that originate from the ERC2771Context
forwarder. Such manipulation renders the contract susceptible to attacks that utilize spoofed calls, thus compromising its integrity.
To solve the challenge, the objective is to amass a significant number of tokens through staking and subsequently transfer a predetermined amount to the address 0x123. The first step involves manipulating the contract's reward rate by assuming the identity of the contract owner. This is achieved by invoking the notifyRewardAmount
function—a mechanism that traditionally restricts execution to the owner by verifying that _msgSender()
matches the owner address. The argument supplied to this function should be carefully calculated to yield the exact amount of rewards destined for transfer to the address 0x123, as stipulated by the Challenge contract.
To be specific, the order of calls should be:
- Solver -> Forwarder -> Multicall (Staking) -> Itself (Staking) ->
notifyRewardAmount
function - Solver -> Staking ->
stake
function - Solver -> Staking ->
getReward
function - Solver -> Token ->
transfer
function
After successfully inflating the reward rate, the next phase involves depositing tokens into the staking contract. After allowing some time for reward accumulation—typically spanning a few blocks—the accrued tokens are withdrawn, the rewards are claimed, and the requisite amount is transferred to the address 0x123.
The challenge is now solved and we can get the flag!