Skip to content

Commit

Permalink
Merge pull request #213 from etherfi-protocol/syko/feature/etherfi_op…
Browse files Browse the repository at this point in the history
…eration_parameters
  • Loading branch information
seongyun-ko authored Dec 20, 2024
2 parents 9221502 + 17778b9 commit 02c3d8f
Show file tree
Hide file tree
Showing 3 changed files with 225 additions and 0 deletions.
47 changes: 47 additions & 0 deletions script/deploys/DeployEtherFiOperationParameters.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

import "forge-std/Script.sol";

import "@openzeppelin/contracts/utils/Strings.sol";

import "../../src/Liquifier.sol";
import "../../src/EtherFiRestaker.sol";
import "../../src/helpers/AddressProvider.sol";
import "../../src/UUPSProxy.sol";
import "../../src/helpers/EtherFiOperationParameters.sol";


contract Deploy is Script {
using Strings for string;
AddressProvider public addressProvider;

function run() external {
uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");
address addressProviderAddress = vm.envAddress("CONTRACT_REGISTRY");
addressProvider = AddressProvider(addressProviderAddress);

vm.startBroadcast(deployerPrivateKey);

bool to_upgrade = true;

if (to_upgrade) {
EtherFiOperationParameters instance = EtherFiOperationParameters(0xD0Ff8996DB4bDB46870b7E833b7532f484fEad1A);
EtherFiOperationParameters impl = new EtherFiOperationParameters();
instance.upgradeTo(address(impl));
} else {
EtherFiOperationParameters impl = new EtherFiOperationParameters();
UUPSProxy proxy = new UUPSProxy(address(impl), "");

EtherFiOperationParameters instance = EtherFiOperationParameters(payable(proxy));

instance.updateTagAdmin("ORACLE", 0x566E58ac0F2c4BCaF6De63760C56cC3f825C48f5, true);
instance.updateTagAdmin("EIGENPOD", 0x566E58ac0F2c4BCaF6De63760C56cC3f825C48f5, true);
// instance.updateTagKeyValue("ORACLE", "WITHDRAWAL_TARGET_GAS_PRICE", "12.5"); // 12.5 gwei
// instance.updateTagKeyValue("ORACLE", "TARGET_LIQUIDITY_IN_PERCENT_OF_TVL", "2.0"); // 2.0 % of TVL
// instance.updateTagKeyValue("EIGENPOD", "PROOF_SUBMIT_TARGET_GAS_PRICE", "12.5"); // 12.5 gwei
}

vm.stopBroadcast();
}
}
47 changes: 47 additions & 0 deletions src/helpers/EtherFiOperationParameters.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

import "@openzeppelin-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol";
import "@openzeppelin-upgradeable/contracts/access/OwnableUpgradeable.sol";

contract EtherFiOperationParameters is UUPSUpgradeable, OwnableUpgradeable {
mapping(string => mapping(address => bool)) public tagAdmins;
mapping(string => mapping(string => string)) public tagKeyValues;

event UpdatedAdmin(string tag, address admin, bool allowed);
event UpdatedKeyValue(string tag, string key, string old_value, string new_value);

/// @custom:oz-upgrades-unsafe-allow constructor
constructor() {
_disableInitializers();
}

function initialize() external initializer {
__Ownable_init();
__UUPSUpgradeable_init();
}

function updateTagAdmin(string memory tag, address admin, bool allowed) external onlyOwner {
tagAdmins[tag][admin] = allowed;

emit UpdatedAdmin(tag, admin, allowed);
}

function updateTagKeyValue(string memory tag, string memory key, string memory value) external onlyAdmin(tag) {
string memory old_value = tagKeyValues[tag][key];
tagKeyValues[tag][key] = value;

emit UpdatedKeyValue(tag, key, old_value, value);
}

function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}

function getImplementation() external view returns (address) {
return _getImplementation();
}

modifier onlyAdmin(string memory tag) {
require(tagAdmins[tag][msg.sender], "Only admin can call");
_;
}
}
131 changes: 131 additions & 0 deletions test/EtherFiOperationParameters.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

import "./TestSetup.sol";
import "forge-std/Test.sol";

import "../src/helpers/EtherFiOperationParameters.sol";
import "../src/UUPSProxy.sol";

contract EtherFiOperationParametersTest is TestSetup {

EtherFiOperationParameters operationParameters;
address rando1 = address(0x1); // Non-owner account for testing
address rando2 = address(0x2); // Another non-owner account

function setUp() public {
EtherFiOperationParameters impl = new EtherFiOperationParameters();
UUPSProxy proxy = new UUPSProxy(address(impl), "");

operationParameters = EtherFiOperationParameters(address(proxy));
operationParameters.initialize();
}

function testFuzz_updateTagAdmin(
string calldata tag,
address admin,
bool allowed
) public {
operationParameters.updateTagAdmin(tag, admin, allowed);
assertEq(operationParameters.tagAdmins(tag, admin), allowed);
}

function testFuzz_updateTagKeyValue(
string calldata tag,
string calldata key,
string calldata value1,
string calldata value2
) public {
vm.expectRevert();
operationParameters.updateTagKeyValue(tag, key, value1);

vm.prank(operationParameters.owner());
operationParameters.updateTagAdmin(tag, admin, true);

vm.prank(admin);
operationParameters.updateTagKeyValue(tag, key, value1);
assertEq(operationParameters.tagKeyValues(tag, key), value1);

vm.prank(admin);
operationParameters.updateTagKeyValue(tag, key, value2);
assertEq(operationParameters.tagKeyValues(tag, key), value2);
}

// Test that only the owner can call updateTagAdmin
function testFuzz_updateTagAdmin_onlyOwner(
string calldata tag,
address admin,
bool allowed
) public {
vm.prank(rando1); // Attempt to call from a non-owner account
vm.expectRevert("Ownable: caller is not the owner");
operationParameters.updateTagAdmin(tag, admin, allowed);

// Owner can successfully call the function
vm.prank(operationParameters.owner());
operationParameters.updateTagAdmin(tag, admin, allowed);
assertEq(operationParameters.tagAdmins(tag, admin), allowed);
}

// Test that only an admin can call updateTagKeyValue
function testFuzz_updateTagKeyValue_onlyAdmin(
string calldata tag,
string calldata key,
string calldata value
) public {
// Attempt to call without being an admin
vm.prank(rando1);
vm.expectRevert("Only admin can call");
operationParameters.updateTagKeyValue(tag, key, value);

// Assign admin role to rando1 for the tag
vm.prank(operationParameters.owner());
operationParameters.updateTagAdmin(tag, rando1, true);

// Alice can now update the key value
vm.prank(rando1);
operationParameters.updateTagKeyValue(tag, key, value);
assertEq(operationParameters.tagKeyValues(tag, key), value);
}

// Test the updateTagKeyValue function with multiple updates by an admin
function testFuzz_updateTagKeyValue_asAdmin(
string calldata tag,
string calldata key,
string calldata value1,
string calldata value2
) public {
// Assign admin role to rando2 for the tag
operationParameters.updateTagAdmin(tag, rando2, true);

// Bob updates the key value
vm.prank(rando2);
operationParameters.updateTagKeyValue(tag, key, value1);
assertEq(operationParameters.tagKeyValues(tag, key), value1);

// Bob updates the key value again
vm.prank(rando2);
operationParameters.updateTagKeyValue(tag, key, value2);
assertEq(operationParameters.tagKeyValues(tag, key), value2);
}

// Test that only the owner can upgrade the contract
function test_upgrade_onlyOwner() public {
address newImplementation = address(new EtherFiOperationParameters());

// Attempt to upgrade from a non-owner account
vm.prank(rando1);
vm.expectRevert("Ownable: caller is not the owner");
operationParameters.upgradeTo(newImplementation);

// Owner upgrades successfully
operationParameters.upgradeTo(newImplementation);
assertEq(operationParameters.getImplementation(), newImplementation);
}

function test_upgrade() public {
address newImplementation = address(new EtherFiOperationParameters());
operationParameters.upgradeTo(newImplementation);
assertEq(operationParameters.getImplementation(), newImplementation);
}
}

0 comments on commit 02c3d8f

Please sign in to comment.