Skip to content

Commit

Permalink
feat: use BoringOwnable for VeRecipient
Browse files Browse the repository at this point in the history
  • Loading branch information
ZeframLou committed Apr 14, 2023
1 parent e360b53 commit 5236bc3
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 43 deletions.
3 changes: 0 additions & 3 deletions .gitmodules
Expand Up @@ -13,6 +13,3 @@
[submodule "lib/openzeppelin-contracts"]
path = lib/openzeppelin-contracts
url = https://github.com/OpenZeppelin/openzeppelin-contracts
[submodule "lib/boringsolidity"]
path = lib/boringsolidity
url = https://github.com/boringcrypto/boringsolidity
1 change: 0 additions & 1 deletion lib/boringsolidity
Submodule boringsolidity deleted from 78f481
24 changes: 9 additions & 15 deletions src/VeRecipient.sol
Expand Up @@ -4,12 +4,13 @@ pragma solidity ^0.8.4;
import {CrossChainEnabled} from "openzeppelin-contracts/contracts/crosschain/CrossChainEnabled.sol";

import "./base/Structs.sol";
import {BoringOwnable} from "./base/BoringOwnable.sol";

/// @title VeRecipient
/// @author zefram.eth
/// @notice Recipient on non-Ethereum networks that receives data from the Ethereum beacon
/// and makes vetoken balances available on this network.
abstract contract VeRecipient is CrossChainEnabled {
abstract contract VeRecipient is CrossChainEnabled, BoringOwnable {
/// -----------------------------------------------------------------------
/// Errors
/// -----------------------------------------------------------------------
Expand All @@ -22,7 +23,6 @@ abstract contract VeRecipient is CrossChainEnabled {

event UpdateVeBalance(address indexed user);
event SetBeacon(address indexed newBeacon);
event TransferOwnership(address indexed newOwner);

/// -----------------------------------------------------------------------
/// Constants
Expand All @@ -35,7 +35,6 @@ abstract contract VeRecipient is CrossChainEnabled {
/// -----------------------------------------------------------------------

address public beacon;
address public owner;
mapping(address => Point) public userData;
Point public globalData;
mapping(uint256 => int128) public slopeChanges;
Expand All @@ -44,9 +43,8 @@ abstract contract VeRecipient is CrossChainEnabled {
/// Constructor
/// -----------------------------------------------------------------------

constructor(address beacon_, address owner_) {
constructor(address beacon_, address owner_) BoringOwnable(owner_) {
beacon = beacon_;
owner = owner_;
}

/// -----------------------------------------------------------------------
Expand Down Expand Up @@ -79,24 +77,20 @@ abstract contract VeRecipient is CrossChainEnabled {
emit UpdateVeBalance(user);
}

/// @notice Called by owner from Ethereum via bridge to update the VeBeacon address.
/// -----------------------------------------------------------------------
/// Owner functions
/// -----------------------------------------------------------------------

/// @notice Called by owner to update the beacon address.
/// @dev The beacon address needs to be updateable because VeBeacon needs to be redeployed
/// when support for a new network is added.
/// @param newBeacon The new address
function setBeacon(address newBeacon) external onlyCrossChainSender(owner) {
function setBeacon(address newBeacon) external onlyOwner {
if (newBeacon == address(0)) revert VeRecipient__InvalidInput();
beacon = newBeacon;
emit SetBeacon(newBeacon);
}

/// @notice Called by owner from Ethereum via bridge to update the owner address.
/// @param newOwner The new address
function transferOwnership(address newOwner) external onlyCrossChainSender(owner) {
if (newOwner == address(0)) revert VeRecipient__InvalidInput();
owner = newOwner;
emit TransferOwnership(newOwner);
}

/// -----------------------------------------------------------------------
/// View functions
/// -----------------------------------------------------------------------
Expand Down
62 changes: 62 additions & 0 deletions src/base/BoringOwnable.sol
@@ -0,0 +1,62 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

// Source: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol + Claimable.sol
// Simplified by BoringCrypto

contract BoringOwnableData {
address public owner;
address public pendingOwner;
}

contract BoringOwnable is BoringOwnableData {
error BoringOwnable__ZeroAddress();
error BoringOwnable__NotPendingOwner();
error BoringOwnable__NotOwner();

event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

constructor(address owner_) {
owner = owner_;
emit OwnershipTransferred(address(0), owner_);
}

/// @notice Transfers ownership to `newOwner`. Either directly or claimable by the new pending owner.
/// Can only be invoked by the current `owner`.
/// @param newOwner Address of the new owner.
/// @param direct True if `newOwner` should be set immediately. False if `newOwner` needs to use `claimOwnership`.
/// @param renounce Allows the `newOwner` to be `address(0)` if `direct` and `renounce` is True. Has no effect otherwise.
function transferOwnership(address newOwner, bool direct, bool renounce) public onlyOwner {
if (direct) {
// Checks
if (newOwner == address(0) && !renounce) revert BoringOwnable__ZeroAddress();

// Effects
emit OwnershipTransferred(owner, newOwner);
owner = newOwner;
pendingOwner = address(0);
} else {
// Effects
pendingOwner = newOwner;
}
}

/// @notice Needs to be called by `pendingOwner` to claim ownership.
function claimOwnership() public {
address _pendingOwner = pendingOwner;

// Checks
if (msg.sender != _pendingOwner) revert BoringOwnable__NotPendingOwner();

// Effects
emit OwnershipTransferred(owner, _pendingOwner);
owner = _pendingOwner;
pendingOwner = address(0);
}

/// @notice Only allows the `owner` to execute the function.
modifier onlyOwner() {
if (msg.sender != owner) revert BoringOwnable__NotOwner();
_;
}
}
26 changes: 2 additions & 24 deletions test/VeRecipient.t.sol
Expand Up @@ -22,6 +22,7 @@ contract VeRecipientTest is Test {
MockVeBeacon beacon;
MockVeRecipient recipient;

error BoringOwnable__NotOwner();
error InvalidCrossChainSender(address actual, address expected);

function setUp() public {
Expand Down Expand Up @@ -58,16 +59,6 @@ contract VeRecipientTest is Test {
}
}
function test_transferOwnership(address newOwner) public {
if (newOwner == address(0)) {
vm.expectRevert(VeRecipient.VeRecipient__InvalidInput.selector);
recipient.transferOwnership(newOwner);
} else {
recipient.transferOwnership(newOwner);
assertEq(recipient.owner(), newOwner, "didn't set new owner");
}
}

function test_fail_updateVeBalanceAsRando(
address user,
int128 userBias,
Expand All @@ -92,25 +83,12 @@ contract VeRecipientTest is Test {
recipient.setBeacon(newBeacon);
} else {
vm.startPrank(rando);
vm.expectRevert(abi.encodeWithSelector(InvalidCrossChainSender.selector, rando, address(this)));
vm.expectRevert(BoringOwnable__NotOwner.selector);
recipient.setBeacon(newBeacon);
vm.stopPrank();
}
}
function test_fail_transferOwnershipAsRando(address newOwner) public {
address rando = address(0x69);
if (newOwner == address(0)) {
vm.expectRevert(VeRecipient.VeRecipient__InvalidInput.selector);
recipient.transferOwnership(newOwner);
} else {
vm.startPrank(rando);
vm.expectRevert(abi.encodeWithSelector(InvalidCrossChainSender.selector, rando, address(this)));
recipient.transferOwnership(newOwner);
vm.stopPrank();
}
}

/// -----------------------------------------------------------------------
/// Internal helpers
/// -----------------------------------------------------------------------
Expand Down

0 comments on commit 5236bc3

Please sign in to comment.