Skip to content

Commit

Permalink
add upgrade test for dispatcher from Rc4 -> v3.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
RnkSngh committed May 6, 2024
1 parent cff09c3 commit 6847751
Show file tree
Hide file tree
Showing 7 changed files with 13,017 additions and 30 deletions.
2 changes: 1 addition & 1 deletion test/Dispatcher/Dispatcher.proof.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ abstract contract DispatcherIbcWithRealProofsSuite is IbcEventsEmitter, Dispatch
dispatcherProxy.channelOpenTry(ch1, ChannelOrder.NONE, false, connectionHops1, ch0, proof);
}

function test_ibc_channel_ack_123_a() public {
function test_ibc_channel_ack() public {
Ics23Proof memory proof = load_proof("/test/payload/channel_ack_pending_proof.hex");

vm.expectEmit(true, true, true, true);
Expand Down
10 changes: 3 additions & 7 deletions test/Dispatcher/Dispatcher.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@ import {IbcReceiver} from "../../contracts/interfaces/IbcReceiver.sol";
import {DummyLightClient} from "../../contracts/utils/DummyLightClient.sol";
import "../../contracts/examples/Mars.sol";
import "../../contracts/core/OptimisticLightClient.sol";
import "../utils/Dispatcher.base.t.sol";
import {LocalEnd, ChannelHandshakeSetting, Base} from "../utils/Dispatcher.base.t.sol";
import {DispatcherProofTestUtils} from "./Dispatcher.proof.t.sol";
import {Earth} from "../../contracts/examples/Earth.sol";

abstract contract ChannelHandshakeUtils is Base {
abstract contract ChannelHandshakeUtils is DispatcherProofTestUtils {
string portId;
LocalEnd _local;
Mars mars;
Expand Down Expand Up @@ -293,11 +294,6 @@ contract PacketSenderTestBase is ChannelOpenTestBaseSetup {
function genPacket(uint64 packetSeq) internal view returns (IbcPacket memory) {
return IbcPacket(src, dest, packetSeq, payload, ZERO_HEIGHT, maxTimeout);
}

// genAckPacket generates an ack packet for the given packet sequence
function genAckPacket(string memory packetSeq) internal pure returns (bytes memory) {
return ackToBytes(AckPacket(true, bytes(packetSeq)));
}
}

// Test Chains B receives a packet from Chain A
Expand Down
105 changes: 83 additions & 22 deletions test/upgradeableProxy/Dispatcher.upgrade.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,35 @@ import "../../contracts/core/OptimisticLightClient.sol";
import {ChannelHandshakeTestSuite, ChannelHandshakeTest, ChannelHandshakeUtils} from "../Dispatcher/Dispatcher.t.sol";
import {LocalEnd} from "../utils/Dispatcher.base.t.sol";
import {Base, ChannelHandshakeSetting} from "../utils/Dispatcher.base.t.sol";
import {ChannelEnd, ChannelOrder, IbcEndpoint, IbcPacket, AckPacket, Ibc, Height} from "../../contracts/libs/Ibc.sol";
import {
ChannelEnd,
ChannelOrder,
ChannelState,
IbcEndpoint,
IbcPacket,
AckPacket,
Ibc,
Height
} from "../../contracts/libs/Ibc.sol";
import {IbcUtils} from "../../contracts/libs/IbcUtils.sol";
import {IbcReceiver} from "../../contracts/interfaces/IbcReceiver.sol";
import {IbcReceiver, IbcChannelReceiver} from "../../contracts/interfaces/IbcReceiver.sol";
import {UUPSUpgradeable} from "@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol";
import {OptimisticLightClient} from "../../contracts/core/OptimisticLightClient.sol";
import {IProofVerifier} from "../../contracts/core/OptimisticProofVerifier.sol";
import {DummyLightClient} from "../../contracts/utils/DummyLightClient.sol";

import {IDispatcher} from "../../contracts/interfaces/IDispatcher.sol";
import {DispatcherRc4} from "./upgrades/DispatcherRc4.sol";
import {DispatcherV2Initializable} from "./upgrades/DispatcherV2Initializable.sol";
import {DispatcherV2} from "./upgrades/DispatcherV2.sol";
import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";

abstract contract UpgradeTestUtils {
string[] connectionHops0 = ["dummy-connection-1", "dummy-connection-2"];
string[] connectionHops1 = ["connection-1", "connection-2"];
LocalEnd _localDummy;
ChannelEnd _remoteDummy;

function upgradeDispatcher(string memory portPrefix, address dispatcherProxy)
public
returns (DispatcherV2Initializable newDispatcherImplementation)
Expand All @@ -31,48 +47,81 @@ abstract contract UpgradeTestUtils {
bytes memory initData = abi.encodeWithSignature("initialize(string)", portPrefix);
UUPSUpgradeable(dispatcherProxy).upgradeToAndCall(address(newDispatcherImplementation), initData);
}

function deployDispatcherRC4ProxyAndImpl(string memory initPortPrefix, ILightClient initLightClient)
public
returns (IDispatcher proxy)
{
DispatcherRc4 dispatcherImplementation = new DispatcherRc4();
bytes memory initData =
abi.encodeWithSelector(DispatcherRc4.initialize.selector, initPortPrefix, initLightClient);
proxy = IDispatcher(address(new ERC1967Proxy(address(dispatcherImplementation), initData)));
}
}

contract ChannelHandShakeUpgradeUtil is ChannelHandshakeUtils {
uint32 nextSequenceSendSlot = 153;
uint32 sendPacketCommitmentSlot = 156;
uint32 ackPacketCommitmentSlot = 158;
uint32 nextSequenceAckSlot = 155;
uint32 nextSequenceRecvSlot = 154;
IbcPacket[3] packets;
string payload = "msgPayload";
bytes packet = abi.encodePacked(payload);
uint64 timeoutTimestamp = 1000;

function doChannelHandshake() public {
// Conduct 4-step channel handshake between local and remote end
// Have to pass in receivingDapp because it's hard to parse out the addresss from the portId
function doChannelHandshake(LocalEnd memory le, ChannelEnd memory re, IbcChannelReceiver receivingDapp) public {
// same setup as that run in test_connectChannel_ok
ChannelHandshakeSetting[8] memory settings = createSettings2(true);

LocalEnd memory remote =
LocalEnd(receivingDapp, re.portId, re.channelId, le.connectionHops, le.versionCall, le.versionExpected);

ChannelEnd memory local = ChannelEnd(le.portId, le.channelId, le.versionCall);
string[2] memory versions = ["1.0", "2.0"];
for (uint256 i = 0; i < settings.length; i++) {
for (uint256 j = 0; j < versions.length; j++) {
LocalEnd memory le = _local;
ChannelEnd memory re = _remote;
le.versionCall = versions[j];
le.versionExpected = versions[j];
re.version = versions[j];
remote.versionCall = versions[j];
remote.versionExpected = versions[j];
local.version = versions[j];
channelOpenInit(le, re, settings[i], true);
channelOpenTry(le, re, settings[i], true);
channelOpenTry(remote, local, settings[i], true);
channelOpenAck(le, re, settings[i], true);
channelOpenConfirm(le, re, settings[i], true);
channelOpenConfirm(remote, local, settings[i], true);
}
}
}

function sendOnePacket(bytes32 channelId, uint64 packetSeq) public {
function doProofChannelHandshake(LocalEnd memory le, ChannelEnd memory re, IbcChannelReceiver receivingDapp)
public
{
ChannelHandshakeSetting memory setting = ChannelHandshakeSetting(ChannelOrder.ORDERED, false, true, validProof);

LocalEnd memory remote =
LocalEnd(receivingDapp, re.portId, re.channelId, le.connectionHops, le.versionCall, le.versionExpected);

ChannelEnd memory local = ChannelEnd(le.portId, le.channelId, le.versionCall);
channelOpenInit(le, re, setting, true);
channelOpenTry(remote, local, setting, true);
channelOpenAck(le, re, setting, true);
channelOpenConfirm(remote, local, setting, true);
}

function sendOnePacket(bytes32 channelId, uint64 packetSeq, Mars sender) public {
vm.expectEmit(true, true, true, true);
emit SendPacket(address(mars), channelId, packet, packetSeq, timeoutTimestamp);
mars.greet(payload, channelId, timeoutTimestamp);
emit SendPacket(address(sender), channelId, packet, packetSeq, timeoutTimestamp);
sender.greet(payload, channelId, timeoutTimestamp);
}

function sendPacket(bytes32 channelId) public {
for (uint64 index = 0; index < 3; index++) {
uint64 packetSeq = index + 1;
sendOnePacket(channelId, packetSeq);
sendOnePacket(channelId, packetSeq, mars);
IbcEndpoint memory dest = IbcEndpoint("polyibc.bsc.9876543210", "channel-99");
string memory marsPort = string(abi.encodePacked(portPrefix, getHexBytes(address(mars))));
IbcEndpoint memory src = IbcEndpoint(marsPort, channelId);
Expand All @@ -87,7 +136,7 @@ contract ChannelHandShakeUpgradeUtil is ChannelHandshakeUtils {
slot = keccak256(abi.encode(channelId, slot1));
}

function findPacketCommitmentSlot(address portAddress, bytes32 channelId, uint64 sequence)
function findSendPacketCommitmentSlot(address portAddress, bytes32 channelId, uint64 sequence)
public
view
returns (bytes32 slot)
Expand All @@ -97,6 +146,16 @@ contract ChannelHandShakeUpgradeUtil is ChannelHandshakeUtils {
slot = keccak256(abi.encode(sequence, slot2));
}

function findAckPacketCommitmentSlot(address portAddress, bytes32 channelId, uint64 sequence)
public
view
returns (bytes32 slot)
{
bytes32 slot1 = keccak256(abi.encode(portAddress, ackPacketCommitmentSlot));
bytes32 slot2 = keccak256(abi.encode(channelId, slot1));
slot = keccak256(abi.encode(sequence, slot2));
}

function findNextSequenceAck(address portAddress, bytes32 channelId) public view returns (bytes32 slot) {
bytes32 slot1 = keccak256(abi.encode(portAddress, nextSequenceAckSlot));
slot = keccak256(abi.encode(channelId, slot1));
Expand All @@ -110,37 +169,39 @@ contract ChannelHandShakeUpgradeUtil is ChannelHandshakeUtils {

contract DispatcherUpgradeTest is ChannelHandShakeUpgradeUtil, UpgradeTestUtils {
function setUp() public override {
address targetMarsAddress = 0x71C95911E9a5D330f4D621842EC243EE1343292e;
(dispatcherProxy, dispatcherImplementation) = deployDispatcherProxyAndImpl(portPrefix);
deployCodeTo("contracts/examples/Mars.sol:Mars", abi.encode(address(dispatcherProxy)), targetMarsAddress);
dispatcherProxy.setClientForConnection(connectionHops[0], dummyLightClient);
mars = new Mars(dispatcherProxy);
portId = IbcUtils.addressToPortId(portPrefix, address(mars));
_local = LocalEnd(mars, portId, "channel-1", connectionHops, "1.0", "1.0");
_remote = ChannelEnd("eth2.7E5F4552091A69125d5DfCb7b8C2659029395Bdf", "channel-2", "1.0");
string memory sendingPortId = IbcUtils.addressToPortId(portPrefix, address(mars));
string memory receivingPortId = IbcUtils.addressToPortId(portPrefix, targetMarsAddress);
_local = LocalEnd(mars, sendingPortId, "channel-1", connectionHops, "1.0", "1.0");
_remote = ChannelEnd(receivingPortId, "channel-2", "1.0");

// Add state to test if impacted by upgrade
doChannelHandshake();
doChannelHandshake(_local, _remote, IbcChannelReceiver(targetMarsAddress));
sendPacket(_local.channelId);

// Upgrade dispatcherProxy for tests
upgradeDispatcher("adfsafsa", address(dispatcherProxy));
}

function test_SentPacketState_Conserved() public {
// Check packet state in sendPacketCommitment()[]
uint64 nextSequenceSendValue = uint64(
uint256(vm.load(address(dispatcherProxy), findNextSequenceSendSlot(address(mars), _local.channelId)))
);

assertEq(4, nextSequenceSendValue);

// packets
assert(vm.load(address(dispatcherProxy), findPacketCommitmentSlot(address(mars), _local.channelId, 1)) > 0);
assert(vm.load(address(dispatcherProxy), findPacketCommitmentSlot(address(mars), _local.channelId, 2)) > 0);
assert(vm.load(address(dispatcherProxy), findPacketCommitmentSlot(address(mars), _local.channelId, 3)) > 0);
assert(vm.load(address(dispatcherProxy), findSendPacketCommitmentSlot(address(mars), _local.channelId, 1)) > 0);
assert(vm.load(address(dispatcherProxy), findSendPacketCommitmentSlot(address(mars), _local.channelId, 2)) > 0);
assert(vm.load(address(dispatcherProxy), findSendPacketCommitmentSlot(address(mars), _local.channelId, 3)) > 0);

// Test sending packet with the updated contract
sendOnePacket(_local.channelId, 4);
assert(vm.load(address(dispatcherProxy), findPacketCommitmentSlot(address(mars), _local.channelId, 4)) > 0);
sendOnePacket(_local.channelId, 4, mars);
assert(vm.load(address(dispatcherProxy), findSendPacketCommitmentSlot(address(mars), _local.channelId, 4)) > 0);
uint64 nextSequenceSendAfterSending = uint64(
uint256(vm.load(address(dispatcherProxy), findNextSequenceSendSlot(address(mars), _local.channelId)))
);
Expand Down
Loading

0 comments on commit 6847751

Please sign in to comment.