Skip to content

Commit

Permalink
feat: works
Browse files Browse the repository at this point in the history
  • Loading branch information
gpsanant committed Dec 14, 2024
1 parent 259967d commit 4035287
Show file tree
Hide file tree
Showing 4 changed files with 172 additions and 8 deletions.
39 changes: 39 additions & 0 deletions script/utils/testdata/DeployHelper.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.9;

import "./utils/RelayScript.s.sol";
import "./utils/StrategyToken.sol";

import "../../../src/contracts/strategies/StrategyFactory.sol";
import "../../../src/contracts/core/DelegationManager.sol";
import "../../../src/contracts/core/StrategyManager.sol";

abstract contract DeployHelper is RelayScript {

function _deployStrategy(string memory name, string memory symbol, uint256 initialSupply) internal returns (IERC20, IStrategy) {
StrategyToken token = new StrategyToken(
name,
symbol,
initialSupply,
msg.sender
);
uint64 nonce = vm.getNonce(msg.sender);
IStrategy strategy = _strategyFactory().deployNewStrategy(IERC20(token));
if (vm.getNonce(msg.sender) == nonce) {
vm.setNonce(msg.sender, nonce + 1);
}
return (token, strategy);
}

function _strategyFactory() internal pure returns (StrategyFactory) {
return StrategyFactory(0xad4A89E3cA9b3dc25AABe0aa7d72E61D2Ec66052);
}

function _delegationManager() internal pure returns (DelegationManager) {
return DelegationManager(0x75dfE5B44C2E530568001400D3f704bC8AE350CC);
}

function _strategyManager() internal pure returns (StrategyManager) {
return StrategyManager(0xF9fbF2e35D8803273E214c99BF15174139f4E67a);
}
}
63 changes: 63 additions & 0 deletions script/utils/testdata/DeploySeveralStakedOperators.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.9;

import "./DeployHelper.s.sol";

contract DeploySeveralStakedOperators is DeployHelper {
uint256 constant OPERATOR_TRANSFER_BATCH_SIZE = 10;
uint256 constant OPERATOR_REGISTRATION_BATCH_SIZE = 10;

function run(uint256 numStrategies, uint256 numOperators) public relayBroadcast {
_startBroadcastEOA(msg.sender);

IERC20[] memory tokens = new IERC20[](numStrategies);
IStrategy[] memory strategies = new IStrategy[](numStrategies);
for (uint256 i = 0; i < numStrategies; i++) {
(tokens[i], strategies[i]) = _deployStrategy("Test", "TEST", 1e50);
console.log("deployed strategy %s", address(strategies[i]));
}
_flushQueuedBroadcasts();

address[] memory operators = new address[](numOperators);
uint256[][] memory operatorBalances = new uint256[][](numOperators);
for (uint256 i = 0; i < numOperators; i++) {
// deploy a new relay
operators[i] = address(new Relay());
console.log("deployed operator %s", operators[i]);
uint64 nonce = vm.getNonce(msg.sender);
// transfer some random amount of tokens to the relay
for (uint256 j = 0; j < numStrategies; j++) {
operatorBalances[i] = new uint256[](numStrategies);
operatorBalances[i][j] = vm.randomUint(0, 100e18);
tokens[j].transfer(operators[i], operatorBalances[i][j]);
}
if (nonce == vm.getNonce(msg.sender)) {
vm.setNonce(msg.sender, nonce + uint64(numStrategies));
}

if (i % OPERATOR_TRANSFER_BATCH_SIZE == 0) {
_flushQueuedBroadcasts();
}
}
_stopBroadcast();

for (uint256 i = 0; i < numOperators; i++) {
_startBroadcastRelay(operators[i]);
// approve and deposit into each strategy
for (uint256 j = 0; j < numStrategies; j++) {
if (operatorBalances[i][j] > 0) {
tokens[j].approve(address(_strategyManager()), type(uint256).max);
_strategyManager().depositIntoStrategy(strategies[j], tokens[j], operatorBalances[i][j]);
}
}
// register the relay as an operator
// 0 allocation delay
_delegationManager().registerAsOperator(address(0), 0, "https://example.com");
_stopBroadcast();

if (i % OPERATOR_REGISTRATION_BATCH_SIZE == 0) {
_flushQueuedBroadcasts();
}
}
}
}
62 changes: 54 additions & 8 deletions script/utils/testdata/utils/RelayScript.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,45 +8,91 @@ import "./Relay.sol";

abstract contract RelayScript is Script {
bool private started;
bool private broadcasted;
mapping(address => bool) private isRelay;
mapping(address => bool) private isEOA;
uint256 internal broadcastForkId;

bool internal everStarted;
uint256 internal relayForkId;

modifier relayBroadcast {
_start();
_;
_broadcast();
_flushBroadcasts();
}

function _start() internal {
require(!started, "RelayScript._start: already started");
started = true;

// create a fork of the current state to broadcast on later
broadcastForkId = vm.activeFork();

// create a fork of the current state to prank on now
vm.createSelectFork(vm.envString("ETH_RPC_URL"));
if (!everStarted) {
relayForkId = vm.createFork(vm.envString("ETH_RPC_URL"));
}
vm.selectFork(relayForkId);
vm.startStateDiffRecording();

started = true;
everStarted = true;
}

function _flushQueuedBroadcasts() internal {
// stop broadcasting
(Vm.CallerMode callerMode, address caller, ) = vm.readCallers();
// TODO: why doesn't Vm.CallerMode.NONE work here?
// if we are in the middle of a broadcast, stop it
if (uint8(callerMode) != uint8(0)) {
_stopBroadcast();
}

// flush the queued broadcasts
_flushBroadcasts();
// restart relaying
_start();

// resume broadcasting
if (uint8(callerMode) != uint8(0)) {
if (isRelay[caller]) {
_startBroadcastRelay(caller);
} else if (isEOA[caller]) {
_startBroadcastEOA(caller);
}
}
}

function _broadcastRelay(address relay) internal {
require(started, "RelayScript._broadcastRelay: not started");
vm.prank(relay);
isRelay[relay] = true;
vm.prank(relay);
}

function _broadcastEOA(address eoa) internal {
require(started, "RelayScript._broadcastEOA: not started");
isEOA[eoa] = true;
vm.prank(eoa);
}

function _startBroadcastRelay(address relay) internal {
require(started, "RelayScript._broadcastRelay: not started");
isRelay[relay] = true;
vm.startPrank(relay);
}

function _startBroadcastEOA(address eoa) internal {
require(started, "RelayScript._broadcastEOA: not started");
isEOA[eoa] = true;
vm.startPrank(eoa);
}

function _stopBroadcast() internal {
vm.stopPrank();
}

function _broadcast() internal {
function _flushBroadcasts() internal {
require(started, "RelayScript._broadcast: not started");
require(!broadcasted, "RelayScript._broadcast: already broadcasted");
broadcasted = true;
started = false;

Vm.AccountAccess[] memory accesses = vm.stopAndReturnStateDiff();

Expand Down
16 changes: 16 additions & 0 deletions script/utils/testdata/utils/StrategyToken.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.12;

import "@openzeppelin/contracts/token/ERC20/extensions/draft-ERC20Permit.sol";
import "@openzeppelin/contracts/token/ERC20/presets/ERC20PresetFixedSupply.sol";

contract StrategyToken is ERC20PresetFixedSupply, ERC20Permit {
constructor(
string memory name,
string memory symbol,
uint256 initialSupply,
address owner
) ERC20PresetFixedSupply(name, symbol, initialSupply, owner) ERC20Permit(name) {
// solhint-disable-previous-line no-empty-blocks
}
}

0 comments on commit 4035287

Please sign in to comment.