Skip to content

Commit

Permalink
fix and test genalloc
Browse files Browse the repository at this point in the history
  • Loading branch information
Ramarti committed Dec 17, 2024
1 parent 1b5927c commit 0d3f31e
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 53 deletions.
94 changes: 41 additions & 53 deletions contracts/script/GenerateAlloc.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { IPTokenStaking } from "../src/protocol/IPTokenStaking.sol";
import { UpgradeEntrypoint } from "../src/protocol/UpgradeEntrypoint.sol";
import { UBIPool } from "../src/protocol/UBIPool.sol";

import { ChainIds } from "./utils/ChainIds.sol";
import { EIP1967Helper } from "./utils/EIP1967Helper.sol";
import { InitializableHelper } from "./utils/InitializableHelper.sol";
import { Predeploys } from "../src/libraries/Predeploys.sol";
Expand Down Expand Up @@ -49,87 +50,64 @@ contract GenerateAlloc is Script {

string internal dumpPath = getDumpPath();
bool public saveState = true;
uint256 public constant STORY_CHAIN_ID = 1415; // Story mainnet chain ID. TBD
// Optionally allocate 10k test accounts for devnets/testnets
bool private constant ALLOCATE_10K_TEST_ACCOUNTS = false;
// Optionally keep the timelock admin role for testnets
bool private constant KEEP_TIMELOCK_ADMIN_ROLE = true;

/// @notice this call should only be available from Test.sol, for speed
function disableStateDump() external {
require(block.chainid == 31337, "Only for local tests");
require(block.chainid == ChainIds.LOCAL, "Only for local tests");
saveState = false;
}

/// @dev this call should only be available from Test.sol
function setAdminAddresses(address protocol, address executor, address guardian) external {
require(block.chainid == 31337, "Only for local tests");
require(block.chainid == ChainIds.LOCAL, "Only for local tests");
protocolAdmin = protocol;
timelockExecutor = executor;
timelockGuardian = guardian;
}

/// @notice path where alloc file will be stored
function getDumpPath() internal view returns (string memory) {
if (block.chainid == 1513) {
if (block.chainid == ChainIds.ILIAD) {
return "./iliad-alloc.json";
} else if (block.chainid == 1512) {
} else if (block.chainid == ChainIds.MININET) {
return "./mininet-alloc.json";
} else if (block.chainid == 1315) {
} else if (block.chainid == ChainIds.ODYSSEY_DEVNET) {
return "./odyssey-devnet-alloc.json";
} else if (block.chainid == 1516) {
} else if (block.chainid == ChainIds.ODYSSEY_TESTNET) {
return "./odyssey-testnet-alloc.json";
} else if (block.chainid == 31337) {
} else if (block.chainid == ChainIds.LOCAL) {
return "./local-alloc.json";
} else if (block.chainid == STORY_CHAIN_ID) {
return "./story-alloc.json";
} else if (block.chainid == ChainIds.MAINNET) {
return "./mainnet-alloc.json";
} else {
revert("Unsupported chain id");
}
}

/// @notice Get the minimum delay for the timelock
function getTimelockMinDelay() internal view returns (uint256) {
if (block.chainid == 1513) {
if (block.chainid == ChainIds.ILIAD) {
// Iliad
return 1 days;
} else if (block.chainid == 1512) {
} else if (block.chainid == ChainIds.MININET) {
// Mininet
return 10 seconds;
} else if (block.chainid == 1315) {
} else if (block.chainid == ChainIds.ODYSSEY_DEVNET) {
// Odyssey devnet
return 10 seconds;
} else if (block.chainid == 1516) {
} else if (block.chainid == ChainIds.ODYSSEY_TESTNET) {
// Odyssey testnet
return 1 days;
} else if (block.chainid == 31337) {
} else if (block.chainid == ChainIds.LOCAL) {
// Local
return 10 seconds;
} else {
revert("Unsupported chain id");
}
}

/// @notice Gets the proposers, executors and canceller for the timelocks
function getTimelockControllers()
internal
view
returns (address[] memory proposers, address[] memory executors, address canceller)
{
proposers = new address[](1);
executors = new address[](1);
if (block.chainid == 1513) {
// Iliad
proposers[0] = protocolAdmin;
executors[0] = protocolAdmin;
canceller = protocolAdmin;
return (proposers, executors, canceller);
} else if (block.chainid == 1512 || block.chainid == 1315 || block.chainid == 31337 || block.chainid == 1516) {
// Mininet, Odyssey devnet, Local, Odyssey testnet
proposers[0] = protocolAdmin;
executors[0] = timelockExecutor;
canceller = timelockGuardian;
return (proposers, executors, canceller);
} else if (block.chainid == ChainIds.MAINNET) {
// Mainnet
return 2 days;
} else {
revert("Unsupported chain id");
}
Expand All @@ -146,14 +124,16 @@ contract GenerateAlloc is Script {
if (timelockExecutor == address(0)) {
timelockExecutor = vm.envAddress("TIMELOCK_EXECUTOR_ADDRESS");
}
require(timelockExecutor != address(0), "executor not set");
if (timelockExecutor == address(0)) {
console2.log("TimelockExecutor not set, executing timelock operations is public");
}

if (timelockGuardian == address(0)) {
timelockGuardian = vm.envAddress("TIMELOCK_GUARDIAN_ADDRESS");
}
require(timelockGuardian != address(0), "canceller not set");

if (block.chainid == STORY_CHAIN_ID) {
if (block.chainid == ChainIds.MAINNET) {
require(!KEEP_TIMELOCK_ADMIN_ROLE, "Timelock admin role not allowed on mainnet");
} else {
console2.log("Will timelock admin role be assigned?", KEEP_TIMELOCK_ADMIN_ROLE);
Expand Down Expand Up @@ -217,25 +197,34 @@ contract GenerateAlloc is Script {
// We deploy this with Create3 because we can't set storage variables in constructor with vm.etch

uint256 minDelay = getTimelockMinDelay();
(address[] memory proposers, address[] memory executors, address canceller) = getTimelockControllers();
address[] memory proposers = new address[](1);
proposers[0] = protocolAdmin;
address[] memory executors = new address[](1);
executors[0] = timelockExecutor;
address canceller = timelockGuardian;

bytes memory creationCode = abi.encodePacked(
type(TimelockController).creationCode,
abi.encode(minDelay, proposers, executors, deployer)
abi.encode(minDelay, proposers, executors, protocolAdmin)
);
bytes32 salt = keccak256("STORY_TIMELOCK_CONTROLLER");
timelock = Create3(Predeploys.Create3).deploy(salt, creationCode);

vm.stopPrank();
bytes32 cancellerRole = TimelockController(payable(timelock)).CANCELLER_ROLE();
vm.prank(protocolAdmin);
TimelockController(payable(timelock)).grantRole(
TimelockController(payable(timelock)).CANCELLER_ROLE(),
cancellerRole,
canceller
);
if (!KEEP_TIMELOCK_ADMIN_ROLE) {
bytes32 adminRole = TimelockController(payable(timelock)).DEFAULT_ADMIN_ROLE();
TimelockController(payable(timelock)).renounceRole(
TimelockController(payable(timelock)).DEFAULT_ADMIN_ROLE(),
deployer
adminRole,
protocolAdmin
);
}
vm.stopPrank();
vm.startPrank(deployer);

console2.log("TimelockController deployed at:", timelock);
}
Expand Down Expand Up @@ -410,9 +399,9 @@ contract GenerateAlloc is Script {
// Story's IPGraph precompile
vm.deal(0x0000000000000000000000000000000000000101, 1);
// Allocation
if (block.chainid == STORY_CHAIN_ID) {
if (block.chainid == ChainIds.MAINNET) {
// TBD
} else if (block.chainid == 1315) {
} else if (block.chainid == ChainIds.ODYSSEY_DEVNET) {
// Odyssey devnet alloc
vm.deal(0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266, 100000000 ether);
vm.deal(0xf398C12A45Bc409b6C652E25bb0a3e702492A4ab, 100000000 ether);
Expand All @@ -422,7 +411,7 @@ contract GenerateAlloc is Script {
vm.deal(0x00FCeC044cD73e8eC6Ad771556859b00C9011111, 100000000 ether);
vm.deal(0xb5350B7CaE94C2bF6B2b56Ef6A06cC1153900000, 100000000 ether);
vm.deal(0x13919a0d8603c35DAC923f92D7E4e1D55e993898, 100000000 ether);
} else if (block.chainid == 1516) {
} else if (block.chainid == ChainIds.ODYSSEY_TESTNET) {
// Odyssey testnet alloc
vm.deal(0x5687400189B13551137e330F7ae081142EdfD866, 200000000 ether);
vm.deal(0x56A26642ad963D3542DdAe4d8fdECC396153c2f6, 200000000 ether);
Expand All @@ -443,8 +432,7 @@ contract GenerateAlloc is Script {
vm.deal(0x13919a0d8603c35DAC923f92D7E4e1D55e993898, 100000000 ether);
vm.deal(0x64a2fdc6f7CD8AA42e0bb59bf80bC47bFFbe4a73, 100000000 ether);
}
// Test for big allocations
if (ALLOCATE_10K_TEST_ACCOUNTS && block.chainid != STORY_CHAIN_ID) {
if (ALLOCATE_10K_TEST_ACCOUNTS && block.chainid != ChainIds.MAINNET) {
setTestAllocations();
}
}
Expand Down
11 changes: 11 additions & 0 deletions contracts/script/utils/ChainIds.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;

library ChainIds {
uint256 public constant MAINNET = 1111; // TBD
uint256 public constant ILIAD = 1513;
uint256 public constant MININET = 1512;
uint256 public constant ODYSSEY_DEVNET = 1315;
uint256 public constant ODYSSEY_TESTNET = 1516;
uint256 public constant LOCAL = 31337;
}
31 changes: 31 additions & 0 deletions contracts/test/timelock/Timelock.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -102,4 +102,35 @@ contract TimelockTest is Test {
timelock.execute(target, value, data3, id2, salt3);
assertEq(ipTokenStaking.fee(), 4 ether);
}

function testTimelockMinDelay() public {
address target = address(ipTokenStaking);
uint256 value = 0;
bytes memory data1 = abi.encodeWithSelector(IPTokenStaking.setFee.selector, 2 ether);
bytes32 salt1 = keccak256("SALT_1");
uint256 minDelay = timelock.getMinDelay();

// Scheduling under the min delay should fail
vm.expectRevert(
abi.encodeWithSelector(TimelockController.TimelockInsufficientDelay.selector, minDelay - 1, minDelay)
);
vm.prank(admin);
timelock.schedule(target, value, data1, bytes32(0), salt1, minDelay - 1);

// Scheduling over the min delay should succeed
vm.prank(admin);
timelock.schedule(target, value, data1, bytes32(0), salt1, minDelay + 1 minutes);

// Should revert if we try to execute before scheduled time
vm.warp(block.timestamp + minDelay);
vm.expectRevert();
vm.prank(executor);
timelock.execute(target, value, data1, bytes32(0), salt1);

// Should succeed if we wait for the delay to pass
vm.warp(block.timestamp + minDelay + 1 minutes);
vm.prank(executor);
timelock.execute(target, value, data1, bytes32(0), salt1);
assertEq(ipTokenStaking.fee(), 2 ether);
}
}
24 changes: 24 additions & 0 deletions contracts/test/upgrades/PredeployUpgrades.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -191,4 +191,28 @@ contract PredeployUpgrades is Test {
expectRevertTimelocked(address(proxyAdmin), upgradeAction, expectedReason);
}
}

function testUpgradeLastPredeploy() public {
address newImpl = address(new InitialImplementation());
address lastPredeploy = address(uint160(Predeploys.Namespace) + uint160(Predeploys.NamespaceSize));
ProxyAdmin proxyAdmin = ProxyAdmin(EIP1967Helper.getAdmin(lastPredeploy));
assertEq(proxyAdmin.owner(), address(timelock));

// Upgrade last predeploy to new implementation
performTimelocked(
address(proxyAdmin),
abi.encodeWithSelector(
ProxyAdmin.upgradeAndCall.selector,
ITransparentUpgradeableProxy(lastPredeploy),
newImpl,
""
)
);
assertEq(EIP1967Helper.getImplementation(lastPredeploy), newImpl, "Last predeploy not upgraded");
assertEq(
keccak256(abi.encode(InitialImplementation(lastPredeploy).foo())),
keccak256(abi.encode("bar")),
"Upgraded to wrong iface"
);
}
}

0 comments on commit 0d3f31e

Please sign in to comment.