Skip to content

Instantly share code, notes, and snippets.

@jac18281828
Created April 22, 2024 15:38
Show Gist options
  • Save jac18281828/2a0fbe69c5e714514cc391e666bc734c to your computer and use it in GitHub Desktop.
Save jac18281828/2a0fbe69c5e714514cc391e666bc734c to your computer and use it in GitHub Desktop.
LayerZero Example OFT Test
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.20;
// Mock imports
import { OFTMock } from "./mocks/OFTMock.sol";
import { ERC20Mock } from "./mocks/ERC20Mock.sol";
import { OFTComposerMock } from "./mocks/OFTComposerMock.sol";
// OApp imports
import {
IOAppOptionsType3,
EnforcedOptionParam
} from "@layerzerolabs/lz-evm-oapp-v2/contracts/oapp/libs/OAppOptionsType3.sol";
import { OptionsBuilder } from "@layerzerolabs/lz-evm-oapp-v2/contracts/oapp/libs/OptionsBuilder.sol";
// OFT imports
import { IOFT, SendParam, OFTReceipt } from "@layerzerolabs/lz-evm-oapp-v2/contracts/oft/interfaces/IOFT.sol";
import { MessagingFee, MessagingReceipt } from "@layerzerolabs/lz-evm-oapp-v2/contracts/oft/OFTCore.sol";
import { OFTMsgCodec } from "@layerzerolabs/lz-evm-oapp-v2/contracts/oft/libs/OFTMsgCodec.sol";
import { OFTComposeMsgCodec } from "@layerzerolabs/lz-evm-oapp-v2/contracts/oft/libs/OFTComposeMsgCodec.sol";
// OZ imports
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
// Forge imports
import "forge-std/console.sol";
// DevTools imports
import { TestHelperOz5 } from "@layerzerolabs/test-devtools-evm-foundry/contracts/TestHelperOz5.sol";
contract MyOFTTest is TestHelperOz5 {
using OptionsBuilder for bytes;
uint32 aEid = 1;
uint32 bEid = 2;
OFTMock aOFT;
OFTMock bOFT;
address public userA = address(0x1);
address public userB = address(0x2);
uint256 public initialBalance = 100 ether;
function setUp() public virtual override {
vm.deal(userA, 1000 ether);
vm.deal(userB, 1000 ether);
super.setUp();
setUpEndpoints(2, LibraryType.UltraLightNode);
aOFT = OFTMock(
_deployOApp(type(OFTMock).creationCode, abi.encode("aOFT", "aOFT", address(endpoints[aEid]), address(this)))
);
bOFT = OFTMock(
_deployOApp(type(OFTMock).creationCode, abi.encode("bOFT", "bOFT", address(endpoints[bEid]), address(this)))
);
// config and wire the ofts
address[] memory ofts = new address[](2);
ofts[0] = address(aOFT);
ofts[1] = address(bOFT);
this.wireOApps(ofts);
// mint tokens
aOFT.mint(userA, initialBalance);
bOFT.mint(userB, initialBalance);
}
function test_constructor() public {
assertEq(aOFT.owner(), address(this));
assertEq(bOFT.owner(), address(this));
assertEq(aOFT.balanceOf(userA), initialBalance);
assertEq(bOFT.balanceOf(userB), initialBalance);
assertEq(aOFT.token(), address(aOFT));
assertEq(bOFT.token(), address(bOFT));
}
function test_send_oft() public {
uint256 tokensToSend = 1 ether;
bytes memory options = OptionsBuilder.newOptions().addExecutorLzReceiveOption(200_000, 0);
SendParam memory sendParam =
SendParam(bEid, addressToBytes32(userB), tokensToSend, tokensToSend, options, "", "");
MessagingFee memory fee = aOFT.quoteSend(sendParam, false);
assertEq(aOFT.balanceOf(userA), initialBalance);
assertEq(bOFT.balanceOf(userB), initialBalance);
vm.prank(userA);
aOFT.send{ value: fee.nativeFee }(sendParam, fee, payable(address(this)));
verifyPackets(bEid, addressToBytes32(address(bOFT)));
assertEq(aOFT.balanceOf(userA), initialBalance - tokensToSend);
assertEq(bOFT.balanceOf(userB), initialBalance + tokensToSend);
}
function test_send_oft_compose_msg() public {
uint256 tokensToSend = 1 ether;
OFTComposerMock composer = new OFTComposerMock();
bytes memory options =
OptionsBuilder.newOptions().addExecutorLzReceiveOption(200_000, 0).addExecutorLzComposeOption(0, 500_000, 0);
bytes memory composeMsg = hex"1234";
SendParam memory sendParam =
SendParam(bEid, addressToBytes32(address(composer)), tokensToSend, tokensToSend, options, composeMsg, "");
MessagingFee memory fee = aOFT.quoteSend(sendParam, false);
assertEq(aOFT.balanceOf(userA), initialBalance);
assertEq(bOFT.balanceOf(address(composer)), 0);
vm.prank(userA);
(MessagingReceipt memory msgReceipt, OFTReceipt memory oftReceipt) =
aOFT.send{ value: fee.nativeFee }(sendParam, fee, payable(address(this)));
verifyPackets(bEid, addressToBytes32(address(bOFT)));
// lzCompose params
uint32 dstEid_ = bEid;
address from_ = address(bOFT);
bytes memory options_ = options;
bytes32 guid_ = msgReceipt.guid;
address to_ = address(composer);
bytes memory composerMsg_ = OFTComposeMsgCodec.encode(
msgReceipt.nonce, aEid, oftReceipt.amountReceivedLD, abi.encodePacked(addressToBytes32(userA), composeMsg)
);
this.lzCompose(dstEid_, from_, options_, guid_, to_, composerMsg_);
assertEq(aOFT.balanceOf(userA), initialBalance - tokensToSend);
assertEq(bOFT.balanceOf(address(composer)), tokensToSend);
assertEq(composer.from(), from_);
assertEq(composer.guid(), guid_);
assertEq(composer.message(), composerMsg_);
assertEq(composer.executor(), address(this));
assertEq(composer.extraData(), composerMsg_); // default to setting the extraData to the message as well to test
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment