Skip to content
Merged
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
15 changes: 9 additions & 6 deletions hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,16 @@ const config: HardhatUserConfig = {
},
},
solidity: {
version: "0.7.5",
settings: {
optimizer: {
enabled: true,
runs: 200,
compilers: [
{
version: "0.7.5",
settings: { optimizer: { enabled: true, runs: 200 } },
},
},
{
version: "0.8.26",
settings: { viaIR: true, optimizer: { enabled: true, runs: 200 } },
},
]
},
networks: {
hardhat: {
Expand Down
214 changes: 214 additions & 0 deletions test/arbitrum/ArbitrumBridgeTest.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
// forge test --match-path test/arbitrum/ArbitrumBridgeTest.t.sol -vvv
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {Test, console, console2} from "forge-std/Test.sol";
import {IGovernorBeta} from "../interfaces/IGovernorBeta.sol";
import {ITimelock} from "../interfaces/ITimelock.sol";
import {ICtx} from "../interfaces/ICtx.sol";
import {IArbitrumInboxErrors} from "../interfaces/IArbitrumInboxErrors.sol";

interface IPerennialCollateral {
function claimFee() external;
}

interface IL1MessageRelayer {
function relayMessage(
address target,
bytes memory payLoad,
uint256 maxSubmissionCost,
uint256 maxGas,
uint256 gasPriceBid
) external returns (uint256);
}

interface IL2MessageExecutor {
function executeMessage(bytes calldata payLoad) external;
}

interface IArbitrumTreasury {
function executeTransaction(
address target,
uint256 value,
string memory signature,
bytes memory data
) external payable returns (bytes memory);
}

library AddressAliasHelper {
uint160 constant OFFSET = uint160(0x1111000000000000000000000000000000001111);

/// @notice Utility function that converts the address in the L1 that submitted a tx to
/// the inbox to the msg.sender viewed in the L2
/// @param l1Address the address in the L1 that triggered the tx to L2
/// @return l2Address L2 address as viewed in msg.sender
function applyL1ToL2Alias(address l1Address)
internal
pure
returns (address l2Address)
{
l2Address = address(uint160(l1Address) + OFFSET);
}

/// @notice Utility function that converts the msg.sender viewed in the L2 to the
/// address in the L1 that submitted a tx to the inbox
/// @param l2Address L2 address as viewed in msg.sender
/// @return l1Address the address in the L1 that triggered the tx to L2
function undoL1ToL2Alias(address l2Address)
internal
pure
returns (address l1Address)
{
l1Address = address(uint160(l2Address) - OFFSET);
}
}

interface IERC20 {
function balanceOf(address account) external returns (uint256);
}

contract AbritrumBridgeTest is Test {
ICtx ctx = ICtx(0x321C2fE4446C7c963dc41Dd58879AF648838f98D);
IGovernorBeta public governorBeta =
IGovernorBeta(0x874C5D592AfC6803c3DD60d6442357879F196d5b);
ITimelock public timelock =
ITimelock(0xa54074b2cc0e96a43048d4a68472F7F046aC0DA8);
IL1MessageRelayer l1MessageRelayer =
IL1MessageRelayer(0x209c23DB16298504354112fa4210d368e1d564dA);
// 0x3769b6aA269995297a539BEd7a463105466733A5 --> L2MessageExecutorProxy.so
IL2MessageExecutor l2MessageExecutor =
IL2MessageExecutor(0x3769b6aA269995297a539BEd7a463105466733A5);
IArbitrumTreasury arbitrumTreasury =
IArbitrumTreasury(0x9474B771Fb46E538cfED114Ca816A3e25Bb346CF);
IPerennialCollateral perennialCollateral =
IPerennialCollateral(0xAF8CeD28FcE00ABD30463D55dA81156AA5aEEEc2);

IERC20 dsu = IERC20(0x52C64b8998eB7C80b6F526E99E29ABdcC86B841b);

uint256 public ethereumMainnetForkId;
uint256 public arbitrumMainnetForkId;
address user = address(0x51);

function setUp() public {
string memory ETHEREUM_MAINNET_RPC_URL = vm.envString(
"ETHEREUM_MAINNET_RPC_URL"
);
string memory ARBITRUM_MAINNET_RPC_URL = vm.envString("ARBITRUM_API_URL");
ethereumMainnetForkId = vm.createFork(ETHEREUM_MAINNET_RPC_URL);
arbitrumMainnetForkId = vm.createFork(ARBITRUM_MAINNET_RPC_URL);

vm.selectFork(ethereumMainnetForkId);
deal(address(ctx), user, 900_000 ether);
vm.prank(user);
ctx.delegate(user);
}

function createAndExecuteGovernanceProposal(
address[] memory targets,
uint256[] memory values,
string[] memory signatures,
bytes[] memory calldatas,
string memory description
) internal {
vm.startPrank(user);
vm.roll(block.number + 100);
governorBeta.propose(targets, values, signatures, calldatas, description);
uint256 proposalID = governorBeta.latestProposalIds(user);
vm.roll(block.number + governorBeta.votingDelay() + 1);
governorBeta.castVote(proposalID, true);
vm.roll(block.number + governorBeta.votingPeriod() + 1);
governorBeta.queue(proposalID);
vm.warp(block.timestamp + timelock.delay() + 1 days);
governorBeta.execute(proposalID);
assertEq(
uint256(governorBeta.state(proposalID)),
uint256(IGovernorBeta.ProposalState.Executed)
);
vm.stopPrank();
}

function test() external {
vm.selectFork(ethereumMainnetForkId);
address l2Target = address(l2MessageExecutor);
bytes memory executorPayload = abi.encode(
address(arbitrumTreasury),
abi.encodeWithSelector(
IArbitrumTreasury.executeTransaction.selector,
address(perennialCollateral), // target
0, // value
"claimFee()", // signature
bytes("") // data
)
);
console2.log(
"=================================================================================="
);
console2.log("payload to feed the script for calculating gas related data");
console2.logBytes(executorPayload);
console2.log(
"=================================================================================="
);

address[] memory targets = new address[](1);
uint256[] memory values = new uint256[](1);
string[] memory signatures = new string[](1);
bytes[] memory calldatas = new bytes[](1);

bytes memory l2CallData = abi.encodeWithSelector(
IL2MessageExecutor.executeMessage.selector,
executorPayload
);

targets[0] = address(l1MessageRelayer);
values[0] = 349782448131600;
signatures[0] = "relayMessage(address,bytes,uint256,uint256,uint256)";
calldatas[0] = abi.encode(
l2Target,
l2CallData,
344212668313600,
111311,
50038000
);
string memory description = "Claim TCAP Perp Fees";
console2.log(
"=================================================================================="
);
console2.log("targets[0]", targets[0]);
console2.log(
"=================================================================================="
);
console2.log("values[0]", values[0]);
console2.log(
"=================================================================================="
);
console2.log("signatures[0]", signatures[0]);
console2.log(
"=================================================================================="
);
console2.log("calldatas[0]");
console2.logBytes(calldatas[0]);
console2.log(
"=================================================================================="
);
console2.log("description", description);
console2.log(
"=================================================================================="
);
createAndExecuteGovernanceProposal(
targets,
values,
signatures,
calldatas,
description
);
vm.selectFork(arbitrumMainnetForkId);
vm.startPrank(
AddressAliasHelper.applyL1ToL2Alias(address(l1MessageRelayer))
);
uint256 oldBalance = dsu.balanceOf(address(arbitrumTreasury));
(bool success, ) = l2Target.call(l2CallData);
require(success, "Message call failed");
uint256 newBalance = dsu.balanceOf(address(arbitrumTreasury));
assertTrue((newBalance - oldBalance) > 15887 ether);
}
}
66 changes: 3 additions & 63 deletions test/ccip/GovernanceCCIPIntegrationTest.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,69 +8,9 @@ import {Client} from "@chainlink/contracts-ccip/src/v0.8/ccip/libraries/Client.s
import {GovernanceCCIPRelay, IGovernanceCCIPRelay} from "contracts/ccip/GovernanceCCIPRelay.sol";
import {GovernanceCCIPReceiver, IGovernanceCCIPReceiver} from "contracts/ccip/GovernanceCCIPReceiver.sol";
import {NumberUpdater} from "contracts/mocks/NumberUpdater.sol";

interface IGovernorBeta {
enum ProposalState {
Pending,
Active,
Canceled,
Defeated,
Succeeded,
Queued,
Expired,
Executed
}

function votingDelay() external pure returns (uint256);

function votingPeriod() external pure returns (uint256);

function state(uint256 proposalId) external view returns (ProposalState);

function propose(
address[] memory targets,
uint256[] memory values,
string[] memory signatures,
bytes[] memory calldatas,
string memory description
) external returns (uint256);

function queue(uint256 proposalId) external;

function execute(uint256 proposalId) external payable;

function castVote(uint256 proposalId, bool support) external;

function latestProposalIds(address) external returns (uint256);
}

interface ITimelock {
function delay() external returns (uint256);

function queueTransaction(
address target,
uint256 value,
string memory signature,
bytes memory data,
uint256 eta
) external returns (bytes32);

function executeTransaction(
address target,
uint256 value,
string memory signature,
bytes memory data,
uint256 eta
) external payable returns (bytes memory);

function admin() external returns (address);

function acceptAdmin() external;
}

interface ICtx {
function delegate(address delegatee) external;
}
import {IGovernorBeta} from "../interfaces/IGovernorBeta.sol";
import {ITimelock} from "../interfaces/ITimelock.sol";
import {ICtx} from "../interfaces/ICtx.sol";

interface IPriceRegistry {
error StaleGasPrice(
Expand Down
Loading
Loading