Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simple ImmutableBeaconProxy implementation #19

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
pragma solidity ^0.8.0;

import {IBeacon} from './interfaces/IBeacon.sol';
import {Proxy} from './Proxy.sol';
import {Proxy} from '../oz-common/Proxy.sol';
import {Address} from '../oz-common/Address.sol';

/**
Expand All @@ -16,12 +16,15 @@ import {Address} from '../oz-common/Address.sol';
contract ImmutableBeaconProxy is Proxy {
address internal immutable _beacon;

event ImmutableBeaconSet(address indexed beacon);

constructor(address beacon) {
require(Address.isContract(beacon), 'INVALID_BEACON');
require(Address.isContract(IBeacon(beacon).implementation()), 'INVALID_IMPLEMENTATION');

// there is no initialization call, because we expect that implementation should have no storage
_beacon = beacon;
emit ImmutableBeaconSet(beacon);
}

/**
Expand Down
68 changes: 68 additions & 0 deletions src/contracts/immutable-beacon-proxy/UpgradeableBeacon.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (proxy/beacon/UpgradeableBeacon.sol)

pragma solidity ^0.8.0;

import './interfaces/IBeacon.sol';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this import this way?

import {Ownable} from '../oz-common/Ownable.sol';
import {Address} from '../oz-common/Address.sol';

/**
* @dev This contract is used in conjunction with one or more instances of {BeaconProxy} to determine their
* implementation contract, which is where they will delegate all function calls.
*
* An owner is able to change the implementation the beacon points to, thus upgrading the proxies that use this beacon.
*/
contract UpgradeableBeacon is IBeacon, Ownable {
address private _implementation;

/**
* @dev Emitted when the implementation returned by the beacon is changed.
*/
event Upgraded(address indexed implementation);

/**
* @dev Sets the address of the initial implementation, and the deployer account as the owner who can upgrade the
* beacon.
*/
constructor(address implementation_) {
_setImplementation(implementation_);
}

/**
* @dev Returns the current implementation address.
*/
function implementation() public view virtual override returns (address) {
return _implementation;
}

/**
* @dev Upgrades the beacon to a new implementation.
*
* Emits an {Upgraded} event.
*
* Requirements:
*
* - msg.sender must be the owner of the contract.
* - `newImplementation` must be a contract.
*/
function upgradeTo(address newImplementation) public virtual onlyOwner {
_setImplementation(newImplementation);
emit Upgraded(newImplementation);
}

/**
* @dev Sets the implementation contract address for this beacon
*
* Requirements:
*
* - `newImplementation` must be a contract.
*/
function _setImplementation(address newImplementation) private {
require(
Address.isContract(newImplementation),
'UpgradeableBeacon: implementation is not a contract'
);
_implementation = newImplementation;
}
}
2 changes: 1 addition & 1 deletion src/contracts/transparent-proxy/ERC1967Proxy.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

pragma solidity ^0.8.0;

import './Proxy.sol';
import '../oz-common/Proxy.sol';
import './ERC1967Upgrade.sol';

/**
Expand Down
6 changes: 5 additions & 1 deletion test/ImmutableBeaconProxy.t.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import 'forge-std/Test.sol';
import {ImmutableBeaconProxy, IBeacon} from '../src/contracts/transparent-proxy/ImmutableBeaconProxy.sol';
import {ImmutableBeaconProxy, IBeacon} from '../src/contracts/immutable-beacon-proxy/ImmutableBeaconProxy.sol';

contract ImplementationMock {}

Expand All @@ -22,10 +22,14 @@ contract ImmutableBeaconProxyMock is ImmutableBeaconProxy {
}

contract ImmutableBeaconProxyTest is Test {
event ImmutableBeaconSet(address indexed beacon);

function testResolvesImplementationCorrectly() public {
address implementation = address(new ImplementationMock());
address beacon = address(new BeaconMock(implementation));

vm.expectEmit(true, false, false, true);
emit ImmutableBeaconSet(beacon);
assertEq(implementation, (new ImmutableBeaconProxyMock(beacon)).implementation());
}

Expand Down