Created
May 1, 2024 23:02
-
-
Save jac18281828/e0d3d29237995ce0d5b035fcac00fcb5 to your computer and use it in GitHub Desktop.
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.22; | |
// 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"; | |
import { ETHx } from "../contracts/ETHx.sol"; | |
import { ETHxOFTMock } from "./mocks/ETHxOFTMock.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 ETHxOFTTest is TestHelperOz5 { | |
using OptionsBuilder for bytes; | |
uint32 aEid = 1; | |
uint32 bEid = 2; | |
OFTMock aOFT; | |
ETHx erc20; | |
ETHxOFTMock 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); | |
address erc20Mock = vm.addr(1001); | |
mockEthx(erc20Mock); | |
erc20 = ETHx(erc20Mock); | |
super.setUp(); | |
setUpEndpoints(2, LibraryType.UltraLightNode); | |
aOFT = OFTMock( | |
_deployOApp(type(OFTMock).creationCode, abi.encode("aOFT", "aOFT", address(endpoints[aEid]), address(this))) | |
); | |
bOFT = ETHxOFTMock( | |
_deployOApp(type(ETHxOFTMock).creationCode, abi.encode(erc20Mock, address(endpoints[bEid]), address(this))) | |
); | |
erc20.grantRole(erc20.PAUSER_ROLE(), address(bOFT)); | |
erc20.grantRole(erc20.MINTER_ROLE(), address(bOFT)); | |
erc20.grantRole(erc20.BURNER_ROLE(), address(bOFT)); | |
// 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); | |
vm.prank(address(bOFT)); | |
bOFT.mint(userB, initialBalance); | |
} | |
function testConstructor() 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(erc20)); | |
} | |
function testBalanceOf() public { | |
address user1 = vm.addr(0x1); | |
address user2 = vm.addr(0x2); | |
vm.prank(address(bOFT)); | |
erc20.mint(user1, 100); | |
assertEq(100, bOFT.balanceOf(user1)); | |
assertEq(0, bOFT.balanceOf(user2)); | |
} | |
function testSendOft() 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 testSendOftComposeMsg() 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 | |
} | |
function mockEthx(address ethxMock) internal { | |
ETHx implementation = new ETHx(); | |
bytes memory code = address(implementation).code; | |
vm.etch(ethxMock, code); | |
ETHx mock = ETHx(ethxMock); | |
mock.initialize(address(this)); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment