Skip to content

Commit

Permalink
feat: add tests and scripts
Browse files Browse the repository at this point in the history
  • Loading branch information
fbac committed Dec 18, 2024
1 parent b490c21 commit daa1ad7
Show file tree
Hide file tree
Showing 11 changed files with 408 additions and 47 deletions.
2 changes: 1 addition & 1 deletion contracts/remappings.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
@openzeppelin/contracts/=dependencies/@openzeppelin-contracts-5.1.0/
@openzeppelin-contracts-upgradeable/=dependencies/@openzeppelin-contracts-upgradeable-5.1.0/
@openzeppelin/contracts/=dependencies/@openzeppelin-contracts-5.1.0/
forge-std/=dependencies/forge-std-1.9.4/
34 changes: 34 additions & 0 deletions contracts/script/DeployGroupMessages.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;

import "forge-std/src/Script.sol";
import "forge-std/src/Vm.sol";
import "src/GroupMessages.sol";
import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";

contract DeployGroupMessages is Script {
function run() external {
uint256 privateKey = vm.envUint("PRIVATE_KEY");
address deployer = vm.addr(privateKey);
vm.startBroadcast(privateKey);

// Step 1: Deploy the implementation contract.
GroupMessages groupMessagesImpl = new GroupMessages();

// Step 2: Deploy the proxy contract.
ERC1967Proxy proxy =
new ERC1967Proxy(
address(groupMessagesImpl),
abi.encodeWithSelector(GroupMessages.initialize.selector, deployer)
);

console.log(
'{"deployer":"%s","proxy":"%s","implementation":"%s"}',
deployer,
address(proxy),
address(groupMessagesImpl)
);

vm.stopBroadcast();
}
}
34 changes: 34 additions & 0 deletions contracts/script/DeployIdentityUpdates.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;

import "forge-std/src/Script.sol";
import "forge-std/src/Vm.sol";
import "src/IdentityUpdates.sol";
import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";

contract DeployIdentityUpdates is Script {
function run() external {
uint256 privateKey = vm.envUint("PRIVATE_KEY");
address deployer = vm.addr(privateKey);
vm.startBroadcast(privateKey);

// Step 1: Deploy the implementation contract
IdentityUpdates idUpdatesImpl = new IdentityUpdates();

// Step 2: Deploy the proxy contract
ERC1967Proxy proxy =
new ERC1967Proxy(
address(idUpdatesImpl),
abi.encodeWithSelector(IdentityUpdates.initialize.selector, deployer)
);

console.log(
'{"deployer":"%s","proxy":"%s","implementation":"%s"}',
deployer,
address(proxy),
address(idUpdatesImpl)
);

vm.stopBroadcast();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
pragma solidity 0.8.28;

import {Script, console} from "forge-std/src/Script.sol";
import "../src/Nodes.sol";
import "src/Nodes.sol";

contract Deployer is Script {
function setUp() public {}
Expand Down
28 changes: 0 additions & 28 deletions contracts/script/DeployerGroupMessages.s.sol

This file was deleted.

36 changes: 36 additions & 0 deletions contracts/script/upgrades/UpgradeGroupMessages.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;

import "forge-std/src/Script.sol";
import "forge-std/src/Vm.sol";
import "src/GroupMessages.sol";
import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";

contract UpgradeGroupMessages is Script {
function run() external {
address proxyAddress = vm.envAddress("XMTP_GROUP_MESSAGES_PROXY_ADDRESS");
require(proxyAddress != address(0), "XMTP_GROUP_MESSAGES_PROXY_ADDRESS not set");

uint256 privateKey = vm.envUint("PRIVATE_KEY");
address upgrader = vm.addr(privateKey);
vm.startBroadcast(privateKey);

// Step 1: Deploy the new implementation contract.
GroupMessages newImplementation = new GroupMessages();

// Step 2: Initialize the proxy.
GroupMessages proxy = GroupMessages(proxyAddress);

// Step 3: Upgrade the proxy pointer to the new implementation.
proxy.upgradeToAndCall(address(newImplementation), "");

console.log(
'{"upgrader":"%s","proxy":"%s","newImplementation":"%s"}',
upgrader,
address(proxy),
address(newImplementation)
);

vm.stopBroadcast();
}
}
36 changes: 36 additions & 0 deletions contracts/script/upgrades/UpgradeIdentityUpdates.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;

import "forge-std/src/Script.sol";
import "forge-std/src/Vm.sol";
import "src/IdentityUpdates.sol";
import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";

contract UpgradeGroupMessages is Script {
function run() external {
address proxyAddress = vm.envAddress("XMTP_IDENTITY_UPDATES_PROXY_ADDRESS");
require(proxyAddress != address(0), "XMTP_IDENTITY_UPDATES_PROXY_ADDRESS not set");

uint256 privateKey = vm.envUint("PRIVATE_KEY");
address upgrader = vm.addr(privateKey);
vm.startBroadcast(privateKey);

// Step 1: Deploy the new implementation contract.
IdentityUpdates newImplementation = new IdentityUpdates();

// Step 2: Initialize the proxy.
IdentityUpdates proxy = IdentityUpdates(proxyAddress);

// Step 3: Upgrade the proxy pointer to the new implementation.
proxy.upgradeToAndCall(address(newImplementation), "");

console.log(
'{"upgrader":"%s","proxy":"%s","newImplementation":"%s"}',
upgrader,
address(proxy),
address(newImplementation)
);

vm.stopBroadcast();
}
}
15 changes: 13 additions & 2 deletions contracts/src/GroupMessages.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,21 @@ contract GroupMessages is Initializable, AccessControlUpgradeable, UUPSUpgradeab
event MessageSent(bytes32 groupId, bytes message, uint64 sequenceId);
event UpgradeAuthorized(address deployer, address newImplementation);

error InvalidMessage();

uint64 private sequenceId;

/// @dev Reserved storage gap for future upgrades
uint256[50] private __gap;

/// @notice Initializes the contract with the deployer as admin.
function initialize() public initializer {
function initialize(address _admin) public initializer {
require(_admin != address(0), "Admin address cannot be zero");
__UUPSUpgradeable_init();
__AccessControl_init();
__Pausable_init();
_grantRole(DEFAULT_ADMIN_ROLE, msg.sender);

_grantRole(DEFAULT_ADMIN_ROLE, _admin);
}

/// @notice Pauses the contract.
Expand All @@ -35,6 +42,9 @@ contract GroupMessages is Initializable, AccessControlUpgradeable, UUPSUpgradeab
/// @param groupId The group ID.
/// @param message The message in bytes.
function addMessage(bytes32 groupId, bytes calldata message) public whenNotPaused {
/// @dev 78 bytes contains the minimum length of a valid message.
require(message.length >= 78, InvalidMessage());

/// @dev Incrementing the sequence ID is safe here due to the extremely large limit of uint64.
unchecked {
sequenceId++;
Expand All @@ -46,6 +56,7 @@ contract GroupMessages is Initializable, AccessControlUpgradeable, UUPSUpgradeab
/// @dev Authorizes the upgrade of the contract.
/// @param newImplementation The address of the new implementation.
function _authorizeUpgrade(address newImplementation) internal override onlyRole(DEFAULT_ADMIN_ROLE) {
require(newImplementation != address(0), "New implementation cannot be zero address");
emit UpgradeAuthorized(msg.sender, newImplementation);
}
}
15 changes: 13 additions & 2 deletions contracts/src/IdentityUpdates.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,21 @@ contract IdentityUpdates is Initializable, AccessControlUpgradeable, UUPSUpgrade
event IdentityUpdateCreated(bytes32 inboxId, bytes update, uint64 sequenceId);
event UpgradeAuthorized(address deployer, address newImplementation);

error InvalidIdentityUpdate();

uint64 private sequenceId;

/// @dev Reserved storage gap for future upgrades
uint256[50] private __gap;

/// @notice Initializes the contract with the deployer as admin.
function initialize() public initializer {
function initialize(address _admin) public initializer {
require(_admin != address(0), "Admin address cannot be zero");
__UUPSUpgradeable_init();
__AccessControl_init();
__Pausable_init();
_grantRole(DEFAULT_ADMIN_ROLE, msg.sender);

_grantRole(DEFAULT_ADMIN_ROLE, _admin);
}

/// @notice Pauses the contract.
Expand All @@ -35,6 +42,9 @@ contract IdentityUpdates is Initializable, AccessControlUpgradeable, UUPSUpgrade
/// @param inboxId The inbox ID.
/// @param update The identity update in bytes.
function addIdentityUpdate(bytes32 inboxId, bytes calldata update) public whenNotPaused {
/// @dev 104 bytes contains the minimum length of a valid IdentityUpdate.
require(update.length >= 104, InvalidIdentityUpdate());

/// @dev Incrementing the sequence ID is safe here due to the extremely large limit of uint64.
unchecked {
sequenceId++;
Expand All @@ -46,6 +56,7 @@ contract IdentityUpdates is Initializable, AccessControlUpgradeable, UUPSUpgrade
/// @dev Authorizes the upgrade of the contract.
/// @param newImplementation The address of the new implementation.
function _authorizeUpgrade(address newImplementation) internal override onlyRole(DEFAULT_ADMIN_ROLE) {
require(newImplementation != address(0), "New implementation cannot be zero address");
emit UpgradeAuthorized(msg.sender, newImplementation);
}
}
Loading

0 comments on commit daa1ad7

Please sign in to comment.