Skip to content

Commit

Permalink
fix: replace guardianModule addr with opsMultisig for VT purchase wit…
Browse files Browse the repository at this point in the history
…h pufETH (#75)

* fix: replace guardianModule addr with opsMultisig for VT purchase with PufETH

* fix: mainnet fork test
  • Loading branch information
ksatyarth2 authored Nov 5, 2024
1 parent 35b4759 commit e0047f1
Show file tree
Hide file tree
Showing 7 changed files with 37 additions and 13 deletions.
7 changes: 6 additions & 1 deletion mainnet-contracts/script/DeployPuffer.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ contract DeployPuffer is BaseScript {
address rewardsCoordinator;
address eigenSlasher;
address treasury;
address operationsMultisig;

function run(GuardiansDeployment calldata guardiansDeployment, address pufferVault, address oracle)
public
Expand All @@ -77,20 +78,23 @@ contract DeployPuffer is BaseScript {
eigenSlasher = 0xD92145c07f8Ed1D392c1B88017934E301CC1c3Cd;
rewardsCoordinator = address(0); //@todo
treasury = vm.envAddress("TREASURY");
operationsMultisig = 0xC0896ab1A8cae8c2C1d27d011eb955Cca955580d;
} else if (isAnvil()) {
// Local chain / tests
eigenPodManager = address(new EigenPodManagerMock());
delegationManager = address(new DelegationManagerMock());
rewardsCoordinator = address(new RewardsCoordinatorMock());
eigenSlasher = vm.envOr("EIGEN_SLASHER", address(1)); // @todo
treasury = address(1);
operationsMultisig = address(2);
} else {
// Holesky https://github.com/Layr-Labs/eigenlayer-contracts?tab=readme-ov-file#current-testnet-deployment
eigenPodManager = 0x30770d7E3e71112d7A6b7259542D1f680a70e315;
delegationManager = 0xA44151489861Fe9e3055d95adC98FbD462B948e7;
eigenSlasher = 0xcAe751b75833ef09627549868A04E32679386e7C;
treasury = 0x61A44645326846F9b5d9c6f91AD27C3aD28EA390;
rewardsCoordinator = 0xAcc1fb458a1317E886dB376Fc8141540537E68fE;
operationsMultisig = 0xDDDeAfB492752FC64220ddB3E7C9f1d5CcCdFdF0;
}

operationsCoordinator = new OperationsCoordinator(PufferOracleV2(oracle), address(accessManager), 500); // 500 BPS = 5%
Expand All @@ -101,7 +105,8 @@ contract DeployPuffer is BaseScript {
guardianModule: payable(guardiansDeployment.guardianModule),
treasury: payable(treasury),
pufferVault: payable(pufferVault),
pufferOracle: IPufferOracleV2(oracle)
pufferOracle: IPufferOracleV2(oracle),
operationsMultisig: operationsMultisig
});

NoImplementation(payable(address(validatorTicketProxy))).upgradeToAndCall(
Expand Down
3 changes: 2 additions & 1 deletion mainnet-contracts/script/DeployVTImplementation.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ contract DeployVTImplementation is DeployerHelper {
guardianModule: payable(address(_getGuardianModule())),
treasury: payable(_getTreasury()),
pufferVault: payable(_getPufferVault()),
pufferOracle: IPufferOracle(address(_getPufferOracle()))
pufferOracle: IPufferOracle(address(_getPufferOracle())),
operationsMultisig: _getOPSMultisig()
});

//@todo Double check reinitialization
Expand Down
3 changes: 2 additions & 1 deletion mainnet-contracts/script/UpgradeValidatorTicket.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ contract UpgradeValidatorTicket is DeployerHelper {
guardianModule: payable(address(_getGuardianModule())),
treasury: payable(_getTreasury()),
pufferVault: payable(_getPufferVault()),
pufferOracle: IPufferOracle(address(_getPufferOracle()))
pufferOracle: IPufferOracle(address(_getPufferOracle())),
operationsMultisig: _getOPSMultisig()
});

validatorTicket = ValidatorTicket(payable(_getValidatorTicket()));
Expand Down
14 changes: 12 additions & 2 deletions mainnet-contracts/src/ValidatorTicket.sol
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ contract ValidatorTicket is
*/
IPufferOracle public immutable override PUFFER_ORACLE;

/**
* @inheritdoc IValidatorTicket
*/
address public immutable override OPERATIONS_MULTISIG;

/**
* @dev Basis point scale
*/
Expand All @@ -68,7 +73,8 @@ contract ValidatorTicket is
address payable guardianModule,
address payable treasury,
address payable pufferVault,
IPufferOracle pufferOracle
IPufferOracle pufferOracle,
address operationsMultisig
) {
if (
guardianModule == address(0) || treasury == address(0) || pufferVault == address(0)
Expand All @@ -80,6 +86,7 @@ contract ValidatorTicket is
GUARDIAN_MODULE = guardianModule;
PUFFER_VAULT = pufferVault;
TREASURY = treasury;
OPERATIONS_MULTISIG = operationsMultisig;
_disableInitializers();
}

Expand Down Expand Up @@ -249,6 +256,9 @@ contract ValidatorTicket is

/**
* @dev Internal function to process the purchase of Validator Tickets with pufETH
* @notice The guardians' portion of pufETH fees is sent to the Operations Multisig since the
* GuardianModule cannot handle ERC20-compatible pufETH. This differs from ETH purchases where
* the guardians' portion goes directly to the GuardianModule.
* @param recipient The address to receive the minted VTs
* @param vtAmount The amount of Validator Tickets to purchase
* @return pufEthUsed The amount of pufETH used for the purchase
Expand Down Expand Up @@ -279,7 +289,7 @@ contract ValidatorTicket is
ValidatorTicket storage $ = _getValidatorTicketStorage();

uint256 treasuryAmount = _sendPufETH(TREASURY, pufEthUsed, $.protocolFeeRate);
uint256 guardiansAmount = _sendPufETH(GUARDIAN_MODULE, pufEthUsed, $.guardiansFeeRate);
uint256 guardiansAmount = _sendPufETH(OPERATIONS_MULTISIG, pufEthUsed, $.guardiansFeeRate);
uint256 burnAmount = pufEthUsed - (treasuryAmount + guardiansAmount);

PufferVaultV3(PUFFER_VAULT).burn(burnAmount);
Expand Down
5 changes: 5 additions & 0 deletions mainnet-contracts/src/interface/IValidatorTicket.sol
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,11 @@ interface IValidatorTicket {
*/
function PUFFER_ORACLE() external view returns (IPufferOracle);

/**
* @notice Returns the Operations Multisig
*/
function OPERATIONS_MULTISIG() external view returns (address);

/**
* @notice Retrieves the current protocol fee rate
* @return The current protocol fee rate
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ contract ValidatorTicketMainnetTest is MainnetForkTestHelper {
uint256 public constant INITIAL_GUARDIANS_FEE = 50; // 0.5%

function setUp() public override {
vm.createSelectFork(vm.rpcUrl("mainnet"), 21074115);
vm.createSelectFork(vm.rpcUrl("mainnet"), 21120959);

// Label accounts for better trace output
for (uint256 i = 0; i < TOKEN_HOLDERS.length; i++) {
Expand Down Expand Up @@ -58,6 +58,7 @@ contract ValidatorTicketMainnetTest is MainnetForkTestHelper {
assertTrue(validatorTicket.GUARDIAN_MODULE() != address(0));
assertTrue(validatorTicket.PUFFER_VAULT() != address(0));
assertTrue(validatorTicket.TREASURY() != address(0));
assertTrue(validatorTicket.OPERATIONS_MULTISIG() != address(0));
}

function test_purchase_validator_ticket_with_pufeth() public {
Expand Down Expand Up @@ -86,7 +87,7 @@ contract ValidatorTicketMainnetTest is MainnetForkTestHelper {
uint256 vtAmount = 2000 ether;
address recipient = dave;
address treasury = validatorTicket.TREASURY();
address guardianModule = validatorTicket.GUARDIAN_MODULE();
address operationsMultisig = validatorTicket.OPERATIONS_MULTISIG();

uint256 vtPrice = IPufferOracle(address(validatorTicket.PUFFER_ORACLE())).getValidatorTicketPrice();
uint256 requiredETH = vtAmount.mulDiv(vtPrice, 1 ether, Math.Rounding.Ceil);
Expand All @@ -95,7 +96,7 @@ contract ValidatorTicketMainnetTest is MainnetForkTestHelper {
deal(address(validatorTicket.PUFFER_VAULT()), recipient, pufEthAmount);

uint256 initialTreasuryBalance = IERC20(validatorTicket.PUFFER_VAULT()).balanceOf(treasury);
uint256 initialGuardianBalance = IERC20(validatorTicket.PUFFER_VAULT()).balanceOf(guardianModule);
uint256 initialOperationsMultisigBalance = IERC20(validatorTicket.PUFFER_VAULT()).balanceOf(operationsMultisig);
uint256 initialBurnedAmount = IERC20(validatorTicket.PUFFER_VAULT()).totalSupply();

vm.startPrank(recipient);
Expand All @@ -115,9 +116,9 @@ contract ValidatorTicketMainnetTest is MainnetForkTestHelper {
"Treasury should receive 5% of pufETH"
);
assertEq(
IERC20(validatorTicket.PUFFER_VAULT()).balanceOf(guardianModule) - initialGuardianBalance,
IERC20(validatorTicket.PUFFER_VAULT()).balanceOf(operationsMultisig) - initialOperationsMultisigBalance,
expectedGuardianAmount,
"Guardians should receive 0.5% of pufETH"
"Operations Multisig should receive 0.5% of pufETH"
);
assertEq(
initialBurnedAmount - IERC20(validatorTicket.PUFFER_VAULT()).totalSupply(),
Expand Down
7 changes: 4 additions & 3 deletions mainnet-contracts/test/unit/ValidatorTicket.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,7 @@ contract ValidatorTicketTest is UnitTestHelper {
uint256 vtAmount = 2000 ether; // Want to mint 2000 VTs
address recipient = actors[0];
address treasury = validatorTicket.TREASURY();
address operationsMultisig = validatorTicket.OPERATIONS_MULTISIG();

uint256 vtPrice = pufferOracle.getValidatorTicketPrice();
uint256 requiredETH = vtAmount.mulDiv(vtPrice, 1 ether, Math.Rounding.Ceil);
Expand All @@ -261,7 +262,7 @@ contract ValidatorTicketTest is UnitTestHelper {
_givePufETH(pufEthAmount, recipient);

uint256 initialTreasuryBalance = pufferVault.balanceOf(treasury);
uint256 initialGuardianBalance = pufferVault.balanceOf(address(guardianModule));
uint256 initialOpsMultisigBalance = pufferVault.balanceOf(operationsMultisig);
uint256 initialBurnedAmount = pufferVault.totalSupply();

vm.startPrank(recipient);
Expand All @@ -282,9 +283,9 @@ contract ValidatorTicketTest is UnitTestHelper {
"Treasury should receive 5% of pufETH"
);
assertEq(
pufferVault.balanceOf(address(guardianModule)) - initialGuardianBalance,
pufferVault.balanceOf(operationsMultisig) - initialOpsMultisigBalance,
expectedGuardianAmount,
"Guardians should receive 0.5% of pufETH"
"Operations Multisig should receive 0.5% of pufETH"
);
assertEq(
initialBurnedAmount - pufferVault.totalSupply(), expectedBurnAmount, "Remaining pufETH should be burned"
Expand Down

0 comments on commit e0047f1

Please sign in to comment.