Skip to content
Draft
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
8 changes: 4 additions & 4 deletions crates/node/assets/zone-dev-genesis.json

Large diffs are not rendered by default.

17 changes: 14 additions & 3 deletions specs/ref-impls/src/interfaces/IZone.sol
Original file line number Diff line number Diff line change
Expand Up @@ -474,9 +474,20 @@ interface IZoneFactory {
function zoneCount() external view returns (uint32);

/// @notice Returns the stored metadata for a zone.
/// @param zoneId The zone ID to query.
/// @return info The zone metadata recorded for `zoneId`.
function zones(uint32 zoneId) external view returns (ZoneInfo memory);
function zones(uint32 id)
external
view
returns (
uint32 zoneId,
address portal,
address initialToken,
address admin,
address sequencer,
bytes32 genesisBlockHash,
bytes32 genesisTempoBlockHash,
uint64 genesisTempoBlockNumber,
string memory rpcUrl
);

/// @notice Returns whether an address is a portal deployed by this factory.
/// @param portal The portal address to check.
Expand Down
7 changes: 3 additions & 4 deletions specs/ref-impls/src/tempo/SwapAndDepositRouter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ import {
EncryptedDepositPayload,
IWithdrawalReceiver,
IZoneFactory,
IZonePortal,
ZoneInfo
IZonePortal
} from "../interfaces/IZone.sol";
import { IStablecoinDEX } from "tempo-std/interfaces/IStablecoinDEX.sol";
import { ITIP20 } from "tempo-std/interfaces/ITIP20.sol";
Expand Down Expand Up @@ -77,8 +76,8 @@ contract SwapAndDepositRouter is IWithdrawalReceiver {
revert UnauthorizedMessenger();
}

ZoneInfo memory sourceZone = zoneFactory.zones(sourceZoneId);
if (sourceZone.portal != sourcePortal) {
(, address registeredPortal,,,,,,,) = zoneFactory.zones(sourceZoneId);
if (registeredPortal != sourcePortal) {
revert InvalidSourcePortal();
}

Expand Down
29 changes: 27 additions & 2 deletions specs/ref-impls/src/tempo/ZoneFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -173,8 +173,33 @@ contract ZoneFactory is IZoneFactory {
return _nextZoneId - 1;
}

function zones(uint32 zoneId) external view returns (ZoneInfo memory) {
return _zones[zoneId];
function zones(uint32 id)
external
view
returns (
uint32 zoneId,
address portal,
address initialToken,
address admin,
address sequencer,
bytes32 genesisBlockHash,
bytes32 genesisTempoBlockHash,
uint64 genesisTempoBlockNumber,
string memory rpcUrl
)
{
ZoneInfo storage info = _zones[id];
return (
info.zoneId,
info.portal,
info.initialToken,
info.admin,
info.sequencer,
info.genesisBlockHash,
info.genesisTempoBlockHash,
info.genesisTempoBlockNumber,
info.rpcUrl
);
}

function isZonePortal(address portal) external view returns (bool) {
Expand Down
11 changes: 3 additions & 8 deletions specs/ref-impls/src/tempo/ZoneMessenger.sol
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

import {
IWithdrawalReceiver,
IZoneFactory,
IZoneMessenger,
ZoneInfo
} from "../interfaces/IZone.sol";
import { IWithdrawalReceiver, IZoneFactory, IZoneMessenger } from "../interfaces/IZone.sol";
import { ITIP20 } from "tempo-std/interfaces/ITIP20.sol";

/// @title ZoneMessenger
Expand Down Expand Up @@ -45,8 +40,8 @@ contract ZoneMessenger is IZoneMessenger {
external
nonReentrantRelay
{
ZoneInfo memory zone = zoneFactory.zones(zoneId);
if (zone.portal != msg.sender) revert UnauthorizedPortal();
(, address portal,,,,,,,) = zoneFactory.zones(zoneId);
if (portal != msg.sender) revert UnauthorizedPortal();

if (!ITIP20(token).transfer(target, amount)) {
revert TransferFailed();
Expand Down
29 changes: 27 additions & 2 deletions specs/ref-impls/test/tempo/SwapAndDepositRouter.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,33 @@ contract MockZoneFactoryForRouter {
return portalMap[portal];
}

function zones(uint32 zoneId) external view returns (ZoneInfo memory) {
return _zones[zoneId];
function zones(uint32 id)
external
view
returns (
uint32 zoneId,
address portal,
address initialToken,
address admin,
address sequencer,
bytes32 genesisBlockHash,
bytes32 genesisTempoBlockHash,
uint64 genesisTempoBlockNumber,
string memory rpcUrl
)
{
ZoneInfo storage info = _zones[id];
return (
info.zoneId,
info.portal,
info.initialToken,
info.admin,
info.sequencer,
info.genesisBlockHash,
info.genesisTempoBlockHash,
info.genesisTempoBlockNumber,
info.rpcUrl
);
}

}
Expand Down
29 changes: 27 additions & 2 deletions specs/ref-impls/test/tempo/ZoneBridge.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,33 @@ contract MockZoneFactoryForBridgeMessenger {
_zones[zoneId].portal = portal;
}

function zones(uint32 zoneId) external view returns (ZoneInfo memory) {
return _zones[zoneId];
function zones(uint32 id)
external
view
returns (
uint32 zoneId,
address portal,
address initialToken,
address admin,
address sequencer,
bytes32 genesisBlockHash,
bytes32 genesisTempoBlockHash,
uint64 genesisTempoBlockNumber,
string memory rpcUrl
)
{
ZoneInfo storage info = _zones[id];
return (
info.zoneId,
info.portal,
info.initialToken,
info.admin,
info.sequencer,
info.genesisBlockHash,
info.genesisTempoBlockHash,
info.genesisTempoBlockNumber,
info.rpcUrl
);
}

}
Expand Down
31 changes: 23 additions & 8 deletions specs/ref-impls/test/tempo/ZoneFactory.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ contract ZoneFactoryTest is BaseTest {
assertEq(zoneFactory.zoneCount(), 1);
assertTrue(zoneFactory.isZonePortal(portal));

ZoneInfo memory info = zoneFactory.zones(zoneId);
ZoneInfo memory info = _zoneInfo(zoneId);
assertEq(info.zoneId, 1);
assertEq(info.portal, portal);
assertEq(info.initialToken, address(pathUSD));
Expand Down Expand Up @@ -118,7 +118,7 @@ contract ZoneFactoryTest is BaseTest {
// Verify portal references the messenger
ZonePortal portalContract = ZonePortal(portal);
assertEq(portalContract.messenger(), messengerAddr);
assertEq(zoneFactory.zones(zoneId).portal, portal);
assertEq(_zoneInfo(zoneId).portal, portal);
}

function test_createZone_multipleZones() public {
Expand Down Expand Up @@ -160,8 +160,8 @@ contract ZoneFactoryTest is BaseTest {
assertTrue(zoneFactory.isZonePortal(portal1));
assertTrue(zoneFactory.isZonePortal(portal2));

ZoneInfo memory info1 = zoneFactory.zones(zoneId1);
ZoneInfo memory info2 = zoneFactory.zones(zoneId2);
ZoneInfo memory info1 = _zoneInfo(zoneId1);
ZoneInfo memory info2 = _zoneInfo(zoneId2);
assertEq(info1.sequencer, sequencer);
assertEq(info2.sequencer, secondSequencer);
assertEq(ZonePortal(portal1).messenger(), zoneFactory.messenger());
Expand Down Expand Up @@ -352,7 +352,7 @@ contract ZoneFactoryTest is BaseTest {
}

function test_zones_returnsEmptyForNonExistentZone() public view {
ZoneInfo memory info = zoneFactory.zones(999);
ZoneInfo memory info = _zoneInfo(999);
assertEq(info.zoneId, 0);
assertEq(info.portal, address(0));
assertEq(info.initialToken, address(0));
Expand All @@ -377,6 +377,21 @@ contract ZoneFactoryTest is BaseTest {
});
}

function _zoneInfo(uint32 id) internal view returns (ZoneInfo memory info) {
(
info.zoneId,
info.portal,
info.initialToken,
info.admin,
info.sequencer,
info.genesisBlockHash,
info.genesisTempoBlockHash,
info.genesisTempoBlockNumber,
info.rpcUrl
) = zoneFactory.zones(id);
info.verifier = zoneFactory.verifier();
}

/*//////////////////////////////////////////////////////////////
REVERT PATHS
//////////////////////////////////////////////////////////////*/
Expand Down Expand Up @@ -446,7 +461,7 @@ contract ZoneFactoryTest is BaseTest {
ZonePortal(portal).acceptSequencer();

assertEq(ZonePortal(portal).sequencer(), nextSequencer); // portal: current
assertEq(zoneFactory.zones(id).sequencer, sequencer); // factory: snapshot at creation
assertEq(_zoneInfo(id).sequencer, sequencer); // factory: snapshot at creation
}

// Factory ZoneInfo.admin is likewise a snapshot; the portal admin can rotate via the
Expand All @@ -459,7 +474,7 @@ contract ZoneFactoryTest is BaseTest {
ZonePortal(portal).acceptAdmin();

assertEq(ZonePortal(portal).admin(), alice); // portal: current
assertEq(zoneFactory.zones(id).admin, admin); // factory: snapshot at creation
assertEq(_zoneInfo(id).admin, admin); // factory: snapshot at creation
}

/*//////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -499,7 +514,7 @@ contract ZoneFactoryTest is BaseTest {
p.zoneParams = ZoneParams(gh, tgh, tbn);

(uint32 id, address portal) = zoneFactory.createZone(p);
ZoneInfo memory info = zoneFactory.zones(id);
ZoneInfo memory info = _zoneInfo(id);

assertEq(info.admin, adminAddr);
assertEq(info.sequencer, seqAddr);
Expand Down
29 changes: 27 additions & 2 deletions specs/ref-impls/test/tempo/ZoneIntegration.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,33 @@ contract MockZoneFactoryForIntegrationMessenger {
_zones[zoneId].portal = portal;
}

function zones(uint32 zoneId) external view returns (ZoneInfo memory) {
return _zones[zoneId];
function zones(uint32 id)
external
view
returns (
uint32 zoneId,
address portal,
address initialToken,
address admin,
address sequencer,
bytes32 genesisBlockHash,
bytes32 genesisTempoBlockHash,
uint64 genesisTempoBlockNumber,
string memory rpcUrl
)
{
ZoneInfo storage info = _zones[id];
return (
info.zoneId,
info.portal,
info.initialToken,
info.admin,
info.sequencer,
info.genesisBlockHash,
info.genesisTempoBlockHash,
info.genesisTempoBlockNumber,
info.rpcUrl
);
}

}
Expand Down
58 changes: 55 additions & 3 deletions specs/ref-impls/test/tempo/ZoneMessenger.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
import { ZoneMessenger } from "../../src/tempo/ZoneMessenger.sol";
import { BaseTest } from "../BaseTest.t.sol";
import { MockZoneToken } from "../mocks/MockZoneToken.sol";
import { Test } from "forge-std/Test.sol";
import { ITIP20 } from "tempo-std/interfaces/ITIP20.sol";

contract MockZoneFactoryForMessenger {
Expand All @@ -20,8 +21,33 @@ contract MockZoneFactoryForMessenger {
_zones[zoneId].portal = portal;
}

function zones(uint32 zoneId) external view returns (ZoneInfo memory) {
return _zones[zoneId];
function zones(uint32 id)
external
view
returns (
uint32 zoneId,
address portal,
address initialToken,
address admin,
address sequencer,
bytes32 genesisBlockHash,
bytes32 genesisTempoBlockHash,
uint64 genesisTempoBlockNumber,
string memory rpcUrl
)
{
ZoneInfo storage info = _zones[id];
return (
info.zoneId,
info.portal,
info.initialToken,
info.admin,
info.sequencer,
info.genesisBlockHash,
info.genesisTempoBlockHash,
info.genesisTempoBlockNumber,
info.rpcUrl
);
}

}
Expand Down Expand Up @@ -76,6 +102,32 @@ contract RejectingWithdrawalReceiver is IWithdrawalReceiver {

}

contract ZoneMessengerFactoryAbiTest is Test {

function test_relayMessage_decodesFlattenedFactoryGetter() public {
uint32 zoneId = 1;
address portal = address(0x700);
address token = address(0x701);

MockZoneFactoryForMessenger factory = new MockZoneFactoryForMessenger();
factory.setPortal(zoneId, portal);
ZoneMessenger messenger = new ZoneMessenger(address(factory));
AcceptingWithdrawalReceiver receiver = new AcceptingWithdrawalReceiver();

vm.mockCall(
token,
abi.encodeWithSelector(ITIP20.transfer.selector, address(receiver), 1),
abi.encode(true)
);
vm.prank(portal);
messenger.relayMessage(zoneId, token, bytes32("sender"), address(receiver), 1, 500_000, "");

assertEq(receiver.lastZoneId(), zoneId);
assertEq(receiver.lastSourcePortal(), portal);
}

}

contract ZoneMessengerTest is BaseTest {

uint32 internal constant ZONE_ID = 1;
Expand Down Expand Up @@ -150,7 +202,7 @@ contract ZoneMessengerTest is BaseTest {
messenger.relayMessage(ZONE_ID, token, bytes32("sender"), alice, 1, 50_000, "");
}

function test_relayMessage_success() public {
function test_relayMessage_successWithFlattenedFactoryGetter() public {
AcceptingWithdrawalReceiver receiver = new AcceptingWithdrawalReceiver();
bytes32 senderTag = keccak256("sender");
bytes memory data = hex"1234";
Expand Down
Loading
Loading