Skip to content

Commit

Permalink
fmt
Browse files Browse the repository at this point in the history
  • Loading branch information
mdtanrikulu committed Nov 12, 2024
1 parent 121f327 commit 940d09f
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 123 deletions.
40 changes: 11 additions & 29 deletions src/TransparentVerifiableProxy.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,12 @@ import {Initializable} from "@openzeppelin/contracts/proxy/utils/Initializable.s

interface ITransparentVerifiableProxy {
/// @dev See {UUPSUpgradeable-upgradeToAndCall}
function upgradeToAndCall(
address newImplementation,
bytes calldata data
) external payable;
function upgradeToAndCall(address newImplementation, bytes calldata data) external payable;
}

contract TransparentVerifiableProxy is Proxy, Initializable {
// immutable variable (in bytecode)
address immutable public creator;
address public immutable creator;

// storage variables (in storage slots)
uint256 public salt; // Salt, being used creating the proxy (slot 0)
Expand Down Expand Up @@ -48,16 +45,12 @@ contract TransparentVerifiableProxy is Proxy, Initializable {
*
* - If `data` is empty, `msg.value` must be zero.
*/
function initialize(
uint256 _salt,
address _owner,
address implementation,
bytes memory data
) public payable initializer {
require(
implementation != address(0),
"New implementation cannot be the zero address"
);
function initialize(uint256 _salt, address _owner, address implementation, bytes memory data)
public
payable
initializer
{
require(implementation != address(0), "New implementation cannot be the zero address");

salt = _salt;
owner = _owner;
Expand All @@ -72,13 +65,7 @@ contract TransparentVerifiableProxy is Proxy, Initializable {
* the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.
* `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`
*/
function _implementation()
internal
view
virtual
override
returns (address)
{
function _implementation() internal view virtual override returns (address) {
return ERC1967Utils.getImplementation();
}

Expand All @@ -87,9 +74,7 @@ contract TransparentVerifiableProxy is Proxy, Initializable {
*/
function _fallback() internal virtual override {
if (msg.sender == creator) {
if (
msg.sig != ITransparentVerifiableProxy.upgradeToAndCall.selector
) {
if (msg.sig != ITransparentVerifiableProxy.upgradeToAndCall.selector) {
revert ProxyDeniedOwnerAccess();
} else {
_dispatchUpgradeToAndCall();
Expand All @@ -107,10 +92,7 @@ contract TransparentVerifiableProxy is Proxy, Initializable {
* - If `data` is empty, `msg.value` must be zero.
*/
function _dispatchUpgradeToAndCall() private {
(address newImplementation, bytes memory data) = abi.decode(
msg.data[4:],
(address, bytes)
);
(address newImplementation, bytes memory data) = abi.decode(msg.data[4:], (address, bytes));
ERC1967Utils.upgradeToAndCall(newImplementation, data);
}

Expand Down
43 changes: 10 additions & 33 deletions src/VerifiableFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,7 @@ interface IProxy {
}

contract VerifiableFactory {
event ProxyDeployed(
address indexed sender,
address indexed proxyAddress,
uint256 salt,
address implementation
);
event ProxyDeployed(address indexed sender, address indexed proxyAddress, uint256 salt, address implementation);

constructor() {}

Expand All @@ -40,17 +35,12 @@ contract VerifiableFactory {
* @param salt A value provided by the caller to ensure uniqueness of the proxy address.
* @return proxy The address of the deployed `TransparentVerifiableProxy`.
*/
function deployProxy(
address implementation,
uint256 salt
) external returns (address) {
function deployProxy(address implementation, uint256 salt) external returns (address) {
console.log("deploys");
console.logAddress(msg.sender);
bytes32 outerSalt = keccak256(abi.encode(msg.sender, salt));

TransparentVerifiableProxy proxy = new TransparentVerifiableProxy{
salt: outerSalt
}(address(this));
TransparentVerifiableProxy proxy = new TransparentVerifiableProxy{salt: outerSalt}(address(this));

require(isContract(address(proxy)), "Proxy deployment failed");

Expand All @@ -61,19 +51,12 @@ contract VerifiableFactory {
}

// Function to upgrade the proxy's implementation (only owner of proxy can call this)
function upgradeImplementation(
address proxyAddress,
address newImplementation,
bytes memory data
) external {
function upgradeImplementation(address proxyAddress, address newImplementation, bytes memory data) external {
address owner = IProxy(proxyAddress).owner();
require(owner == msg.sender, "Only the owner can upgrade");

// Upgrade the proxy to point to the new implementation
ITransparentVerifiableProxy(payable(proxyAddress)).upgradeToAndCall(
newImplementation,
data
);
ITransparentVerifiableProxy(payable(proxyAddress)).upgradeToAndCall(newImplementation, data);
}

/**
Expand All @@ -99,18 +82,12 @@ contract VerifiableFactory {

// reconstruct the address using CREATE2 and verify it matches
bytes32 outerSalt = keccak256(abi.encode(msg.sender, salt));

// get creation bytecode with constructor arguments
bytes memory bytecode = abi.encodePacked(
type(TransparentVerifiableProxy).creationCode,
abi.encode(address(this))
);

address expectedProxyAddress = Create2.computeAddress(
outerSalt,
keccak256(bytecode),
address(this)
);
bytes memory bytecode =
abi.encodePacked(type(TransparentVerifiableProxy).creationCode, abi.encode(address(this)));

address expectedProxyAddress = Create2.computeAddress(outerSalt, keccak256(bytecode), address(this));

return expectedProxyAddress == proxy;
} catch {}
Expand Down
2 changes: 1 addition & 1 deletion src/mock/MockRegistryV2.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import {MockRegistry} from './MockRegistry.sol';
import {MockRegistry} from "./MockRegistry.sol";

contract MockRegistryV2 is MockRegistry {
function getRegistryVersion() public pure override returns (uint256) {
Expand Down
75 changes: 15 additions & 60 deletions test/VerifiableFactory.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,7 @@ contract VerifiableFactoryTest is Test {
address public maliciousUser;

// ### Events
event ProxyDeployed(
address indexed sender,
address indexed proxyAddress,
uint256 salt,
address implementation
);
event ProxyDeployed(address indexed sender, address indexed proxyAddress, uint256 salt, address implementation);

function setUp() public {
owner = makeAddr("owner");
Expand All @@ -45,43 +40,27 @@ contract VerifiableFactoryTest is Test {

function test_FactoryInitialState() public view {
assertTrue(address(factory) != address(0), "Factory deployment failed");
assertTrue(
address(implementation) != address(0),
"Implementation deployment failed"
);
assertTrue(address(implementation) != address(0), "Implementation deployment failed");
}

function test_DeployProxy() public {
uint256 salt = 1;

// test event emit
vm.expectEmit(true, true, true, true);
emit ProxyDeployed(
owner,
computeExpectedAddress(salt),
salt,
address(implementation)
);
emit ProxyDeployed(owner, computeExpectedAddress(salt), salt, address(implementation));

vm.startPrank(owner);
address proxyAddress = factory.deployProxy(
address(implementation),
salt
);
address proxyAddress = factory.deployProxy(address(implementation), salt);

vm.stopPrank();

// verify proxy deployment
assertTrue(
proxyAddress != address(0),
"Proxy address should not be zero"
);
assertTrue(proxyAddress != address(0), "Proxy address should not be zero");
assertTrue(isContract(proxyAddress), "Proxy should be a contract");

// verify proxy state
TransparentVerifiableProxy proxy = TransparentVerifiableProxy(
payable(proxyAddress)
);
TransparentVerifiableProxy proxy = TransparentVerifiableProxy(payable(proxyAddress));
assertEq(proxy.salt(), salt, "Proxy salt mismatch");
assertEq(proxy.owner(), owner, "Proxy owner mismatch");
assertEq(proxy.creator(), address(factory), "Proxy creator mismatch");
Expand All @@ -106,10 +85,7 @@ contract VerifiableFactoryTest is Test {

// deploy proxy as owner
vm.prank(owner);
address proxyAddress = factory.deployProxy(
address(implementation),
salt
);
address proxyAddress = factory.deployProxy(address(implementation), salt);

// try to upgrade as non-owner (should fail)
vm.prank(maliciousUser);
Expand All @@ -130,22 +106,15 @@ contract VerifiableFactoryTest is Test {

// verify new implementation
MockRegistryV2 upgradedProxy = MockRegistryV2(proxyAddress);
assertEq(
upgradedProxy.getRegistryVersion(),
2,
"Implementation upgrade failed"
);
assertEq(upgradedProxy.getRegistryVersion(), 2, "Implementation upgrade failed");
}

function test_VerifyContract() public {
uint256 salt = 1;

// deploy proxy
vm.prank(owner);
address proxyAddress = factory.deployProxy(
address(implementation),
salt
);
address proxyAddress = factory.deployProxy(address(implementation), salt);

vm.prank(owner);
// verify the contract
Expand All @@ -163,15 +132,10 @@ contract VerifiableFactoryTest is Test {
uint256 salt = 1;

vm.prank(owner);
address proxyAddress = factory.deployProxy(
address(implementation),
salt
);
address proxyAddress = factory.deployProxy(address(implementation), salt);

// test proxy state
TransparentVerifiableProxy proxy = TransparentVerifiableProxy(
payable(proxyAddress)
);
TransparentVerifiableProxy proxy = TransparentVerifiableProxy(payable(proxyAddress));

assertEq(proxy.salt(), salt, "Wrong salt");
assertEq(proxy.owner(), owner, "Wrong owner");
Expand All @@ -187,21 +151,12 @@ contract VerifiableFactoryTest is Test {
return size > 0;
}

function computeExpectedAddress(
uint256 salt
) internal view returns (address) {
function computeExpectedAddress(uint256 salt) internal view returns (address) {
bytes32 outerSalt = keccak256(abi.encode(owner, salt));

bytes memory bytecode = abi.encodePacked(
type(TransparentVerifiableProxy).creationCode,
abi.encode(address(factory))
);
bytes memory bytecode =
abi.encodePacked(type(TransparentVerifiableProxy).creationCode, abi.encode(address(factory)));

return
Create2.computeAddress(
outerSalt,
keccak256(bytecode),
address(factory)
);
return Create2.computeAddress(outerSalt, keccak256(bytecode), address(factory));
}
}

0 comments on commit 940d09f

Please sign in to comment.