Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 47 additions & 1 deletion contracts/messageBridge/MessageBridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,62 @@ import {ReentrancyGuardUpgradeable} from "@openzeppelin/contracts-upgradeable/ut
import {StorageTypes} from "../library/StorageTypes.sol";
import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";

/// @custom:oz-upgrades-unsafe-allow missing-initializer
contract MessageBridge is IMessageBridge, ReentrancyGuardUpgradeable, UUPSUpgradeable, AMBStorage {
address public constant GOV_ADMIN = 0x1212000000000000000000000000000000000000;

uint32 public constant VERSION = 1;

/// @custom:oz-upgrades-unsafe-allow constructor
constructor() {
_disableInitializers();
}

function initialize(
address _management,
uint256 _fee,
uint256 _maxMessageSize,
uint256 _maxNrMessages,
uint256 _executionWindowSeconds
)
external
virtual
onlyAdmin
initializer
{
__initialize(_management, _fee, _maxMessageSize, _maxNrMessages, _executionWindowSeconds);
}

function __initialize(
address _management,
uint256 _fee,
uint256 _maxMessageSize,
uint256 _maxNrMessages,
uint256 _executionWindowSeconds
)
internal
onlyInitializing
{
__ReentrancyGuard_init();
getStorage().management = IBridgeManagement(_management);
if (_fee == 0) revert InvalidFee();
if (_maxMessageSize == 0) revert InvalidValue();
if (_maxNrMessages == 0) revert InvalidValue();

getStorage().messageBridgeState = MessageBridgeState({
paused: true,
sendingPaused: false,
executingPaused: false,
neoToEvmState: StorageTypes.State({nonce: 0, root: 0x0}),
evmToNeoState: StorageTypes.State({nonce: 0, root: 0x0}),
config: MessageConfig({
fee: _fee,
maxMessageSize: _maxMessageSize,
maxNrMessages: _maxNrMessages,
executionWindowSeconds: _executionWindowSeconds
})
});
}

//0x79828e03
error NoAuthorization();
//0x58d620b3
Expand Down
57 changes: 2 additions & 55 deletions contracts/tests/TestMessageBridge.sol
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.25;

import {IBridgeManagement} from "../interfaces/IBridgeManagement.sol";
import {AMBStorage} from "../messageBridge/AMBStorage.sol";
import {AMBTypes} from "../library/AMBTypes.sol";
import {MessageBridgeLib} from "../library/MessageBridgeLib.sol";
import {StorageTypes} from "../library/StorageTypes.sol";
import {MessageBridge} from "../messageBridge/MessageBridge.sol";

contract TestMessageBridge is MessageBridge {
Expand All @@ -22,57 +17,9 @@ contract TestMessageBridge is MessageBridge {
uint256 _executionWindowSeconds
)
external
override
initializer
Copy link

Copilot AI Oct 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The override keyword is used here, but the parent MessageBridge.initialize function is marked as virtual, not as an interface function. Additionally, both this function and the parent use the initializer modifier. When overriding, only one initializer modifier should be used in the inheritance chain to avoid issues. The parent's initializer modifier will not be invoked when this override is called. Consider removing the initializer modifier from this override since __initialize uses onlyInitializing which works correctly in the override pattern.

Suggested change
initializer

Copilot uses AI. Check for mistakes.
{
__ReentrancyGuard_init();
getStorage().management = IBridgeManagement(_management);
_setMessageBridge(_fee, _maxMessageSize, _maxNrMessages, _executionWindowSeconds);
}

function _setMessageBridge(
uint256 _fee,
uint256 _maxMessageSize,
uint256 _maxNrMessages,
uint256 _executionWindowSeconds
)
internal
{
if (_fee == 0) revert InvalidFee();
if (_maxMessageSize == 0) revert InvalidValue();
if (_maxNrMessages == 0) revert InvalidValue();

getStorage().messageBridgeState = MessageBridgeState({
paused: true,
sendingPaused: false,
executingPaused: false,
neoToEvmState: StorageTypes.State({nonce: 0, root: 0x0}),
evmToNeoState: StorageTypes.State({nonce: 0, root: 0x0}),
config: MessageConfig({
fee: _fee,
maxMessageSize: _maxMessageSize,
maxNrMessages: _maxNrMessages,
executionWindowSeconds: _executionWindowSeconds
})
});
}

/// @notice Stores a message in the AMB storage.
/// @param messageData The message data to be stored, including nonce, encoded metadata, and the raw message.
/// @dev This function is used to simulate the storage of a message in the AMB storage.
function storeSingleMessage(AMBTypes.MessageData memory messageData) external {
AMBStorage.AMB storage ambStorage = getStorage();
ambStorage.evmMessages[messageData.nonce] =
AMBStorage.StoredMessage({encodedMetadata: messageData.encodedMetadata, rawMessage: messageData.message});

AMBTypes.MessageType msgType = MessageBridgeLib._readMessageType(messageData.encodedMetadata);
if (msgType == AMBTypes.MessageType.EXECUTABLE) {
uint256 window = ambStorage.messageBridgeState.config.executionWindowSeconds;
// Use the block timestamp to set the expiration timestamp for the executable message
// in case the relayer is down and does not relay the message in time.
ambStorage.evmExecutableStates[messageData.nonce] =
AMBStorage.ExecutableState({executed: false, expirationTimestamp: block.timestamp + window});
}

emit Store(messageData.nonce, messageData.encodedMetadata);
__initialize(_management, _fee, _maxMessageSize, _maxNrMessages, _executionWindowSeconds);
}
}
4 changes: 2 additions & 2 deletions scripts/deploy/bridge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ export async function deployBridge(managementAddress: string, deployer: Wallet,
await bridgeProxy.waitForDeployment();
const bridge = await ethers.getContractAt("TestBridge", await bridgeProxy.getAddress());

console.log("\n📝 Deployment of Bridge");
console.log("\nDeployment of Bridge");
console.log("Bridge Proxy: ", await bridge.getAddress());
console.log("Bridge Logic: ", await upgrades.erc1967.getImplementationAddress(await bridge.getAddress()));

console.log("\n💾 Bridge Configuration");
console.log("\nBridge Configuration");
console.log("Linked Management: ", await bridge.management());
return bridge;
}
Expand Down
12 changes: 6 additions & 6 deletions scripts/deploy/deployAll.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export async function deployAll(): Promise<void> {

await ensureConsistentState(management, bridge, messageBridge, executionManager);

console.log("\n🏁 Summary of Deployed Contracts (without logic addresses)");
console.log("\nSummary of Deployed Contracts (without logic addresses)");
console.log("BridgeManagement: ", managementAddress);
console.log("Bridge: ", bridgeAddress);
console.log("MessageBridge: ", messageBridgeAddress);
Expand All @@ -52,24 +52,24 @@ async function ensureConsistentState(management: TestBridgeManagement, bridge: T
const messageBridgeAddress = await messageBridge.getAddress();
const executionManagerAddress = await executionManager.getAddress();

console.log("\n🔍 Ensuring consistent state across deployed contracts...");
console.log("\nEnsuring consistent state across deployed contracts...");
if (matches(await bridge.management(), managementAddress)) {
console.log(" BridgeManagement address correctly set on Bridge contract");
console.log(" BridgeManagement address correctly set on Bridge contract");
} else {
throw new Error("BridgeManagement address on Bridge does not match deployed management contract address");
}
if (matches(await messageBridge.management(), managementAddress)) {
console.log(" BridgeManagement address correctly set on MessageBridge contract");
console.log(" BridgeManagement address correctly set on MessageBridge contract");
} else {
throw new Error("BridgeManagement address on MessageBridge does not match deployed BridgeManagement contract address");
}
if (matches(await messageBridge.executionManager(), executionManagerAddress)) {
console.log(" ExecutionManager address correctly set on MessageBridge contract");
console.log(" ExecutionManager address correctly set on MessageBridge contract");
} else {
throw new Error("ExecutionManager address on MessageBridge does not match deployed ExecutionManager contract address");
}
if (await executionManager.hasRole(await executionManager.BRIDGE_ROLE(), messageBridgeAddress)) {
console.log(" MessageBridge has bridge role privileges on ExecutionManager contract");
console.log(" MessageBridge has bridge role privileges on ExecutionManager contract");
} else {
throw new Error("MessageBridge does not have bridge role privileges on ExecutionManager contract");
}
Expand Down
4 changes: 2 additions & 2 deletions scripts/deploy/deployNeoToken.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export async function deployNeoTokenContract(deployer: Wallet): Promise<NeoToken
await neoTokenProxy.waitForDeployment();
const neoToken = await ethers.getContractAt("NeoToken", await neoTokenProxy.getAddress());

console.log("\n# Deployment");
console.log("\nDeployment");
console.log("Neo Token Address: ", await neoToken.getAddress());
console.log("Minted Tokens: ", ethers.formatEther(await neoToken.totalSupply()));
return neoToken;
Expand All @@ -25,7 +25,7 @@ async function main() {
const deployer = getPersonalWallet(ethers.provider);
await fundIfLocalNetwork([deployer.address]);
const neoToken = await deployNeoTokenContract(deployer);
console.log("\n# NeoToken Contract Deployment Completed");
console.log("\nNeoToken Contract Deployment Completed");
}

main().catch((error) => {
Expand Down
2 changes: 1 addition & 1 deletion scripts/deploy/executionManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export async function deployExecutionManager(deployer: Wallet, bridgeAddress: an
await executionManager.waitForDeployment();

const contractAddress = await executionManager.getAddress();
console.log("\n📝 Deployment of ExecutionManager");
console.log("\nDeployment of ExecutionManager");
console.log("Execution Manager: ", contractAddress);

// Verify the contract has code deployed
Expand Down
4 changes: 2 additions & 2 deletions scripts/deploy/management.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ export async function deployBridgeManagement(deployer: Wallet): Promise<TestBrid
await managementProxy.waitForDeployment();
const management = await ethers.getContractAt("TestBridgeManagement", await managementProxy.getAddress());

console.log("\n📝 Deployment of BridgeManagement");
console.log("\nDeployment of BridgeManagement");
console.log("BridgeManagement Proxy: ", await management.getAddress());
console.log("BridgeManagement Logic: ", await upgrades.erc1967.getImplementationAddress(await management.getAddress()));

console.log("\n👉 Roles");
console.log("\nRoles");
console.log("Owner: ", await management.owner());
console.log("Relayer: ", await management.getRelayer());
console.log("Validator Threshold: ", (await management.getValidatorThreshold()).toString());
Expand Down
4 changes: 2 additions & 2 deletions scripts/deploy/messageBridge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ export async function deployMessageBridge(managementAddress: string, deployer: W
await msgBridgeProxy.waitForDeployment();
const msgBridge = await ethers.getContractAt("TestMessageBridge", await msgBridgeProxy.getAddress());

console.log("\n📝 Deployment of MessageBridge");
console.log("\nDeployment of MessageBridge");
console.log("MessageBridge Proxy: ", await msgBridge.getAddress());
console.log("MessageBridge Logic: ", await upgrades.erc1967.getImplementationAddress(await msgBridge.getAddress()));

console.log("\n💾 MessageBridge Configuration");
console.log("\nMessageBridge Configuration");
console.log("Management Contract: ", await msgBridge.management());
console.log("MessageBridge Paused: ", await msgBridge.messageBridgePaused());
console.log("MessageBridge Sending Paused: ", await msgBridge.sendingPaused());
Expand Down
Loading