diff --git a/src/TransparentVerifiableProxy.sol b/src/TransparentVerifiableProxy.sol index 76c9cd7..08174af 100644 --- a/src/TransparentVerifiableProxy.sol +++ b/src/TransparentVerifiableProxy.sol @@ -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) @@ -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; @@ -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(); } @@ -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(); @@ -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); } diff --git a/src/VerifiableFactory.sol b/src/VerifiableFactory.sol index c140d88..d21f805 100644 --- a/src/VerifiableFactory.sol +++ b/src/VerifiableFactory.sol @@ -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() {} @@ -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"); @@ -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); } /** @@ -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 {} diff --git a/src/mock/MockRegistryV2.sol b/src/mock/MockRegistryV2.sol index 2631340..99647cd 100644 --- a/src/mock/MockRegistryV2.sol +++ b/src/mock/MockRegistryV2.sol @@ -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) { diff --git a/test/VerifiableFactory.t.sol b/test/VerifiableFactory.t.sol index 16dc699..e1b17f4 100644 --- a/test/VerifiableFactory.t.sol +++ b/test/VerifiableFactory.t.sol @@ -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"); @@ -45,10 +40,7 @@ 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 { @@ -56,32 +48,19 @@ contract VerifiableFactoryTest is Test { // 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"); @@ -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); @@ -130,11 +106,7 @@ 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 { @@ -142,10 +114,7 @@ contract VerifiableFactoryTest is Test { // 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 @@ -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"); @@ -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)); } }