Skip to content

Commit

Permalink
Merge pull request #74 from Tenderize/nv/registry-fix
Browse files Browse the repository at this point in the history
Disallow duplicate tenderizers for the same validator
  • Loading branch information
kyriediculous authored Jan 4, 2024
2 parents 5441fd5 + b822bed commit c09b988
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 13 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@
"scripts": {
"clean": "rimraf cache out",
"lint": "yarn lint:sol && yarn prettier:write",
"lint:sol": "yarn solhint \"{src,test,script}/**/*.sol\"",
"lint:sol": "yarn solhint \"{src}/**/*.sol\"",
"postinstall": "husky install",
"prettier:check": "prettier --check \"**/*.{json,md,yml}\"",
"prettier:write": "prettier --write \"**/*.{json,md,yml}\""
}
}
}
1 change: 1 addition & 0 deletions src/factory/Factory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ contract Factory {
tenderizer = address(tenderizerImpl).clone(abi.encodePacked(asset, validator));

// Reverts if caller is not a registered factory
// Reverts if `validator` already has a registered `tenderizer` for `asset`
Registry(registry).registerTenderizer(asset, validator, tenderizer);
}
}
38 changes: 27 additions & 11 deletions src/registry/Registry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { Adapter } from "core/adapters/Adapter.sol";
contract Registry is Initializable, UUPSUpgradeable, AccessControlUpgradeable, RegistryStorage {
error InvalidAdapter(address adapter);
error InvalidTreasury(address treasury);
error TenderizerAlreadyExists(address asset, address validator, address tenderizer);

event AdapterRegistered(address indexed asset, address indexed adapter);
event NewTenderizer(address indexed asset, address indexed validator, address tenderizer);
Expand Down Expand Up @@ -57,6 +58,14 @@ contract Registry is Initializable, UUPSUpgradeable, AccessControlUpgradeable, R

// Getters

/**
* @notice Returns the address of the adapter for a given asset
* @param asset Address of the underlying asset
*/
function adapter(address asset) external view returns (address) {
return _loadStorage().protocols[asset].adapter;
}

/**
* @notice Returns the address of the tenderizer implementation
*/
Expand All @@ -66,19 +75,19 @@ contract Registry is Initializable, UUPSUpgradeable, AccessControlUpgradeable, R
}

/**
* @notice Returns the address of the unlocks contract
* @notice Returns the address of the treasury
*/
function unlocks() external view returns (address) {
function treasury() external view returns (address) {
Storage storage $ = _loadStorage();
return $.unlocks;
return $.treasury;
}

/**
* @notice Returns the address of the adapter for a given asset
* @param asset Address of the underlying asset
* @notice Returns the address of the unlocks contract
*/
function adapter(address asset) external view returns (address) {
return _loadStorage().protocols[asset].adapter;
function unlocks() external view returns (address) {
Storage storage $ = _loadStorage();
return $.unlocks;
}

/**
Expand All @@ -99,11 +108,13 @@ contract Registry is Initializable, UUPSUpgradeable, AccessControlUpgradeable, R
}

/**
* @notice Returns the address of the treasury
* @notice Returns the address of the tenderizer for a given asset and validator
* @param asset Address of the underlying asset
* @param validator Address of the validator
* @return Address of the tenderizer
*/
function treasury() external view returns (address) {
Storage storage $ = _loadStorage();
return $.treasury;
function getTenderizer(address asset, address validator) external view returns (address) {
return _loadStorage().tenderizers[asset][validator];
}

// Setters
Expand All @@ -129,6 +140,11 @@ contract Registry is Initializable, UUPSUpgradeable, AccessControlUpgradeable, R
* @param tenderizer Address of the tenderizer
*/
function registerTenderizer(address asset, address validator, address tenderizer) external onlyRole(FACTORY_ROLE) {
Storage storage $ = _loadStorage();
if ($.tenderizers[asset][validator] != address(0)) {
revert TenderizerAlreadyExists(asset, validator, $.tenderizers[asset][validator]);
}
$.tenderizers[asset][validator] = tenderizer;
_grantRole(TENDERIZER_ROLE, tenderizer);
emit NewTenderizer(asset, validator, tenderizer);
}
Expand Down
1 change: 1 addition & 0 deletions src/registry/RegistryStorage.sol
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ contract RegistryStorage {
address unlocks;
address treasury;
mapping(address => Protocol) protocols;
mapping(address asset => mapping(address validator => address tenderizer)) tenderizers;
}

function _loadStorage() internal pure returns (Storage storage $) {
Expand Down
10 changes: 10 additions & 0 deletions test/registry/Registry.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,16 @@ contract RegistryTest is Test {
assertEq(registry.hasRole(TENDERIZER_ROLE, tenderizer), true);
}

function test_RegisterTenderizer_RevertsIfExists() public {
vm.prank(owner);
registry.grantRole(FACTORY_ROLE, factory);
vm.startPrank(factory);
registry.registerTenderizer(asset, account, tenderizer);
vm.expectRevert(abi.encodeWithSelector(Registry.TenderizerAlreadyExists.selector, asset, account, tenderizer));
registry.registerTenderizer(asset, account, makeAddr("SECOND_TENDERIZER"));
vm.stopPrank();
}

function test_RegisterTenderizer_RevertIfNotFactory() public {
vm.prank(owner);
vm.expectRevert();
Expand Down

0 comments on commit c09b988

Please sign in to comment.