Commit 80465cd6 authored by Michael Amadi's avatar Michael Amadi Committed by GitHub

add test for L1ChugSplashProxy (#13045)

* add test for L1ChugSplashProxy

* fixes

* fixes
parent 6a871c54
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.15;
// Testing utilities
import { Test } from "forge-std/Test.sol";
// Target contract
import { IL1ChugSplashProxy } from "src/legacy/interfaces/IL1ChugSplashProxy.sol";
import { DeployUtils } from "scripts/libraries/DeployUtils.sol";
contract Owner {
bool public isUpgrading;
function setIsUpgrading(bool _isUpgrading) public {
isUpgrading = _isUpgrading;
}
}
contract Implementation {
function setCode(bytes memory) public pure returns (uint256) {
return 1;
}
function setStorage(bytes32, bytes32) public pure returns (uint256) {
return 2;
}
function setOwner(address) public pure returns (uint256) {
return 3;
}
function getOwner() public pure returns (uint256) {
return 4;
}
function getImplementation() public pure returns (uint256) {
return 5;
}
}
contract L1ChugSplashProxy_Test is Test {
IL1ChugSplashProxy proxy;
address impl;
address owner = makeAddr("owner");
address alice = makeAddr("alice");
function setUp() public {
proxy = IL1ChugSplashProxy(
DeployUtils.create1({
_name: "L1ChugSplashProxy",
_args: DeployUtils.encodeConstructor(abi.encodeCall(IL1ChugSplashProxy.__constructor__, (owner)))
})
);
vm.prank(owner);
assertEq(proxy.getOwner(), owner);
vm.prank(owner);
proxy.setCode(type(Implementation).runtimeCode);
vm.prank(owner);
impl = proxy.getImplementation();
}
/// @notice Tests that the owner can deploy a new implementation with a given runtime code
function test_setCode_whenOwner_succeeds() public {
vm.prank(owner);
proxy.setCode(hex"604260005260206000f3");
vm.prank(owner);
assertNotEq(proxy.getImplementation(), impl);
}
/// @notice Tests that when not the owner, `setCode` delegatecalls the implementation
function test_setCode_whenNotOwner_works() public view {
uint256 ret = Implementation(address(proxy)).setCode(hex"604260005260206000f3");
assertEq(ret, 1);
}
/// @notice Tests that when the owner deploys the same bytecode as the existing implementation,
/// it does not deploy a new implementation
function test_setCode_whenOwnerSameBytecode_works() public {
vm.prank(owner);
proxy.setCode(type(Implementation).runtimeCode);
// does not deploy new implementation
vm.prank(owner);
assertEq(proxy.getImplementation(), impl);
}
/// @notice Tests that when the owner calls `setCode` with insufficient gas to complete the implementation
/// contract's deployment, it reverts.
/// @dev If this solc version/settings change and modifying this proves time consuming, we can just remove it.
function test_setCode_whenOwnerAndDeployOutOfGas_reverts() public {
vm.prank(owner);
vm.expectRevert(bytes("L1ChugSplashProxy: code was not correctly deployed")); // Ran out of gas
proxy.setCode{ gas: 65_000 }(
hex"fefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefefe"
);
}
/// @notice Tests that when the caller is not the owner and the implementation is not set, all calls reverts
function test_calls_whenNotOwnerNoImplementation_reverts() public {
proxy = IL1ChugSplashProxy(
DeployUtils.create1({
_name: "L1ChugSplashProxy",
_args: DeployUtils.encodeConstructor(abi.encodeCall(IL1ChugSplashProxy.__constructor__, (owner)))
})
);
vm.expectRevert(bytes("L1ChugSplashProxy: implementation is not set yet"));
Implementation(address(proxy)).setCode(hex"604260005260206000f3");
}
/// @notice Tests that when the caller is not the owner but the owner has marked `isUpgrading` as true, the call
/// reverts
function test_calls_whenUpgrading_reverts() public {
Owner ownerContract = new Owner();
vm.prank(owner);
proxy.setOwner(address(ownerContract));
ownerContract.setIsUpgrading(true);
vm.expectRevert(bytes("L1ChugSplashProxy: system is currently being upgraded"));
Implementation(address(proxy)).setCode(hex"604260005260206000f3");
}
/// @notice Tests that the owner can set storage of the proxy
function test_setStorage_whenOwner_works() public {
vm.prank(owner);
proxy.setStorage(bytes32(0), bytes32(uint256(42)));
assertEq(vm.load(address(proxy), bytes32(0)), bytes32(uint256(42)));
}
/// @notice Tests that when not the owner, `setStorage` delegatecalls the implementation
function test_setStorage_whenNotOwner_works() public view {
uint256 ret = Implementation(address(proxy)).setStorage(bytes32(0), bytes32(uint256(42)));
assertEq(ret, 2);
assertEq(vm.load(address(proxy), bytes32(0)), bytes32(uint256(0)));
}
/// @notice Tests that the owner can set the owner of the proxy
function test_setOwner_whenOwner_works() public {
vm.prank(owner);
proxy.setOwner(alice);
vm.prank(alice);
assertEq(proxy.getOwner(), alice);
}
/// @notice Tests that when not the owner, `setOwner` delegatecalls the implementation
function test_setOwner_whenNotOwner_works() public {
uint256 ret = Implementation(address(proxy)).setOwner(alice);
assertEq(ret, 3);
vm.prank(owner);
assertEq(proxy.getOwner(), owner);
}
/// @notice Tests that the owner can get the owner of the proxy
function test_getOwner_whenOwner_works() public {
vm.prank(owner);
assertEq(proxy.getOwner(), owner);
}
/// @notice Tests that when not the owner, `getOwner` delegatecalls the implementation
function test_getOwner_whenNotOwner_works() public view {
uint256 ret = Implementation(address(proxy)).getOwner();
assertEq(ret, 4);
}
/// @notice Tests that the owner can get the implementation of the proxy
function test_getImplementation_whenOwner_works() public {
vm.prank(owner);
assertEq(proxy.getImplementation(), impl);
}
/// @notice Tests that when not the owner, `getImplementation` delegatecalls the implementation
function test_getImplementation_whenNotOwner_works() public view {
uint256 ret = Implementation(address(proxy)).getImplementation();
assertEq(ret, 5);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment