Created
April 22, 2024 15:38
-
-
Save jac18281828/2a0fbe69c5e714514cc391e666bc734c to your computer and use it in GitHub Desktop.
LayerZero Example OFT Test
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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