-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
7d3b99e
commit ac347c3
Showing
6 changed files
with
171 additions
and
784 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,169 @@ | ||
// 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 "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) private { | ||
ETHx implementation = new ETHx(); | ||
bytes memory code = address(implementation).code; | ||
vm.etch(ethxMock, code); | ||
ETHx mock = ETHx(ethxMock); | ||
mock.initialize(address(this)); | ||
} | ||
} |
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
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.