Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
177 changes: 124 additions & 53 deletions contracts/scripts/runlogs/2025_10.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,60 +8,131 @@ import { SetupMainnet } from "./utils/Setup.sol";

import { CrossChain } from "./utils/Addresses.sol";

import { Cluster } from "contracts/contracts/interfaces/ISSVNetwork.sol";
import { Mainnet } from "./utils/Addresses.sol";

// Foundry
import { console } from "forge-std/console.sol";

contract Runlogs_2025_10_Mainnet is SetupMainnet {
function run() public {
_2025_10_01();
//_2025_10_02();
}

// ------------------------------------------------------------------
// Oct 3, 2025 - Yield Forward to Computed Merkl Pool Booster
// ------------------------------------------------------------------
function _2025_10_01() internal {
bytes memory campaignData =
hex"b8fef900b383db2dbbf4458c7f46acf5b140f26d603a6d1829963f241b82510e00000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";

vm.startBroadcast(strategist);

console.log("-----");
console.log("strategist address", address(strategist));
console.log("poolBoosterFactoryMerkl address", address(poolBoosterFactoryMerkl));

address poolBoosterAddress = poolBoosterFactoryMerkl.computePoolBoosterAddress({
_campaignType: 45,
_ammPoolAddress: CrossChain.MORPHO_BLUE,
_campaignDuration: 7 days,
campaignData: campaignData,
_salt: uint256(keccak256(abi.encodePacked("Merkl Morpho PB OETH/USDC v1")))
});

console.log("computed address", poolBoosterAddress);

// Run yield forward
oeth.delegateYield(CrossChain.MORPHO_BLUE, poolBoosterAddress);
vm.stopBroadcast();
}

// ------------------------------------------------------------------
// Oct 3+ TODO, 2025 - Create Merkl Pool Booster once Central Registry governance passes
// ------------------------------------------------------------------
function _2025_10_02() internal {
bytes memory campaignData =
hex"b8fef900b383db2dbbf4458c7f46acf5b140f26d603a6d1829963f241b82510e00000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";

vm.startBroadcast(strategist);
// Create the pool booster
poolBoosterFactoryMerkl.createPoolBoosterMerkl({
_campaignType: 45, // Incentivise Borrow rate of OETH/USDC
_ammPoolAddress: CrossChain.MORPHO_BLUE,
_campaignDuration: 7 days,
campaignData: campaignData,
_salt: uint256(keccak256(abi.encodePacked("Merkl Morpho PB OETH/USDC v1")))
});

vm.stopBroadcast();
}
}
function run() public {
// _2025_10_01();
//_2025_10_02();
_2025_10_07();
}

// ------------------------------------------------------------------
// Oct 3, 2025 - Yield Forward to Computed Merkl Pool Booster
// ------------------------------------------------------------------
function _2025_10_01() internal {
bytes
memory campaignData = hex"b8fef900b383db2dbbf4458c7f46acf5b140f26d603a6d1829963f241b82510e00000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";

vm.startBroadcast(strategist);

console.log("-----");
console.log("strategist address", address(strategist));
console.log(
"poolBoosterFactoryMerkl address",
address(poolBoosterFactoryMerkl)
);

address poolBoosterAddress = poolBoosterFactoryMerkl
.computePoolBoosterAddress({
_campaignType: 45,
_ammPoolAddress: CrossChain.MORPHO_BLUE,
_campaignDuration: 7 days,
campaignData: campaignData,
_salt: uint256(
keccak256(abi.encodePacked("Merkl Morpho PB OETH/USDC v1"))
)
});

console.log("computed address", poolBoosterAddress);

// Run yield forward
oeth.delegateYield(CrossChain.MORPHO_BLUE, poolBoosterAddress);
vm.stopBroadcast();
}

// ------------------------------------------------------------------
// Oct 3+ TODO, 2025 - Create Merkl Pool Booster once Central Registry governance passes
// ------------------------------------------------------------------
function _2025_10_02() internal {
bytes
memory campaignData = hex"b8fef900b383db2dbbf4458c7f46acf5b140f26d603a6d1829963f241b82510e00000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";

vm.startBroadcast(strategist);
// Create the pool booster
poolBoosterFactoryMerkl.createPoolBoosterMerkl({
_campaignType: 45, // Incentivise Borrow rate of OETH/USDC
_ammPoolAddress: CrossChain.MORPHO_BLUE,
_campaignDuration: 7 days,
campaignData: campaignData,
_salt: uint256(
keccak256(abi.encodePacked("Merkl Morpho PB OETH/USDC v1"))
)
});

vm.stopBroadcast();
}

// ------------------------------------------------------------------
// Oct 7, 2025 - Deposit 400 SSV to the second SSV cluster and
// 200 SSV to the third SSV cluster
// ------------------------------------------------------------------
function _2025_10_07() internal {
vm.startBroadcast(strategist);

console.log("-----");
console.log("strategist address", address(strategist));
console.log("SSV token address", address(ssv));
console.log("SSV Network address", address(ssvNetwork));

uint256 ssvDepositAmount = 600 * 1e18; // 600 SSV

ssv.approve(address(ssvNetwork), ssvDepositAmount);

uint64[] memory operatorIds = new uint64[](4);
operatorIds[0] = 752;
operatorIds[1] = 753;
operatorIds[2] = 754;
operatorIds[3] = 755;

// Get the SSV Cluster data from the following Hardhat task
// npx hardhat getClusterInfo --operatorids 752,753,754,755 --network mainnet --owner 0x4685dB8bF2Df743c861d71E6cFb5347222992076
ssvNetwork.deposit(
Mainnet.NATIVE_STAKING_STRATEGY_2,
operatorIds,
400 * 1e18, // 400 SSV,
Cluster({
validatorCount: 500,
networkFeeIndex: 97648369159,
index: 9585132,
active: true,
balance: 1066288969170302776597
})
);

operatorIds[0] = 338;
operatorIds[1] = 339;
operatorIds[2] = 340;
operatorIds[3] = 341;

// npx hardhat getClusterInfo --operatorids 338,339,340,341 --network mainnet --owner 0xE98538A0e8C2871C2482e1Be8cC6bd9F8E8fFD63
ssvNetwork.deposit(
Mainnet.NATIVE_STAKING_STRATEGY_3,
operatorIds,
200 * 1e18, // 200 SSV,
Cluster({
validatorCount: 436,
networkFeeIndex: 226592732593,
index: 0,
active: true,
balance: 419059922731900000000
})
);

vm.stopBroadcast();
}
}
20 changes: 16 additions & 4 deletions contracts/scripts/runlogs/README.md
Original file line number Diff line number Diff line change
@@ -1,46 +1,58 @@
# How to use foundry runlogs?

## 1. Ensure all dependencies are installed

At the root of the repo run:

```bash
forge soldeer install
cd contract
yarn install
```

## 2. Execute runlogs

In the `contracts` folder run:

```bash
forge script Runlogs_2025_08_Mainnet
```

> Note: adjust the year, month and chain accordingly.

This generates 2 files (that are `broadcast-ready` for execution) under `contracts/broadcast`:

- run-latest.json
- run-1755456667783.json (with the timestamp corresponding to the execution time)

## 3. Convert runlogs into Safe-compatible JSON

Since these transactions are meant to be executed from the Safe, it is not possible to use `cast`.

To convert a `broadcast-ready` into a Safe-compatible JSON file, use the forge script: `scripts/runlogs/utils/BroadcastConvertor.sol`.
To convert a `broadcast-ready` into a Safe-compatible JSON file, use the forge script: `scripts/runlogs/utils/BroadcastConvertor.sol`.

In the `contracts` folder run:

```bash
forge script BroadcastConvertor --sig "run(string)" contracts/broadcast/2025_09.sol/146/dry-run/
forge script BroadcastConvertor --sig "run(string)" contracts/broadcast/2025_09.s.sol/146/dry-run/
```

> Note adjust the input accordingly:
> first the path to the run file, but stop at the dry-run folder.

This creates, by default, a file named `run-latest-safe.json` in the same location as the input file, ready to be imported into the Safe UI.

### Timelock targeted ?

If on the script, the address used inside `startBroadcast()` is a `Timelock`:
- the Safe-compatible JSON will be adjusted to target the `scheduleBatch` and `executeBatch` functions on the `Timelock` contract.
- two files will be generated: `run-latest-schedule` and `run-latest-execute`.

- the Safe-compatible JSON will be adjusted to target the `scheduleBatch` and `executeBatch` functions on the `Timelock` contract.
- two files will be generated: `run-latest-schedule` and `run-latest-execute`.

## 4. How generates Safe JSON in just one command?

In the `contracts` folder:

```makefile
make script
or
Expand Down
Loading
Loading