-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
test: lz test and improvements to strategy
- Loading branch information
1 parent
52b612d
commit 0ecc737
Showing
9 changed files
with
4,574 additions
and
156 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
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 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
10 changes: 10 additions & 0 deletions
10
src/base/DecodersAndSanitizers/Protocols/PirexEthDecoderAndSanitizer.sol
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,10 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity 0.8.21; | ||
|
||
import { BaseDecoderAndSanitizer } from "src/base/DecodersAndSanitizers/BaseDecoderAndSanitizer.sol"; | ||
|
||
abstract contract PirexEthDecoderAndSanitizer is BaseDecoderAndSanitizer { | ||
function deposit(address receiver, bool) external returns (bytes memory) { | ||
return abi.encodePacked(receiver); | ||
} | ||
} |
17 changes: 17 additions & 0 deletions
17
src/base/DecodersAndSanitizers/SeiyanEthRebalanceDecoderAndSanitizer.sol
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,17 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity 0.8.21; | ||
|
||
import { BaseDecoderAndSanitizer } from "src/base/DecodersAndSanitizers/BaseDecoderAndSanitizer.sol"; | ||
import { ERC4626DecoderAndSanitizer } from "src/base/DecodersAndSanitizers/Protocols/ERC4626DecoderAndSanitizer.sol"; | ||
import { PirexEthDecoderAndSanitizer } from "src/base/DecodersAndSanitizers/Protocols/PirexEthDecoderAndSanitizer.sol"; | ||
import { NativeWrapperDecoderAndSanitizer } from | ||
"src/base/DecodersAndSanitizers/Protocols/NativeWrapperDecoderAndSanitizer.sol"; | ||
|
||
contract SeiyanEthRebalanceDecoderAndSanitizer is | ||
BaseDecoderAndSanitizer, | ||
ERC4626DecoderAndSanitizer, | ||
PirexEthDecoderAndSanitizer, | ||
NativeWrapperDecoderAndSanitizer | ||
{ | ||
constructor(address _boringVault) BaseDecoderAndSanitizer(_boringVault) { } | ||
} |
38 changes: 38 additions & 0 deletions
38
src/base/DecodersAndSanitizers/StargateV2DecoderAndSanitizer.sol
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,38 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity 0.8.21; | ||
|
||
import { BaseDecoderAndSanitizer } from "src/base/DecodersAndSanitizers/BaseDecoderAndSanitizer.sol"; | ||
import { MessagingFee, OFTReceipt, SendParam } from "@layerzerolabs/lz-evm-oapp-v2/contracts/oft/interfaces/IOFT.sol"; | ||
|
||
contract StargateV2DecoderAndSanitizer is BaseDecoderAndSanitizer { | ||
constructor(address _boringVault) BaseDecoderAndSanitizer(_boringVault) { } | ||
|
||
error StargateV2DecoderAndSanitizer_ComposedMsgNotSupported(); | ||
|
||
/** | ||
* @dev _sendParam: | ||
* uint32 dstEid; // Destination endpoint ID. [VERIFY] | ||
* bytes32 to; // Recipient address. [VERIFY] | ||
* uint256 amountLD; // Amount to send in local decimals. | ||
* uint256 minAmountLD; // Minimum amount to send in local decimals. | ||
* bytes extraOptions; // Additional options supplied by the caller to be used in the LayerZero message. | ||
* bytes composeMsg; // The composed message for the send() operation. [NONE] | ||
* bytes oftCmd; // The OFT command to be executed, unused in default OFT implementations. [NONE] | ||
* @dev _fee: | ||
* uint256 nativeFee; | ||
* uint256 lzTokenFee; | ||
*/ | ||
function sendToken( | ||
SendParam memory _sendParam, | ||
MessagingFee memory _messagingFee, | ||
address _refundAddress | ||
) | ||
external | ||
returns (bytes memory) | ||
{ | ||
if (_sendParam.composeMsg.length > 0) { | ||
revert StargateV2DecoderAndSanitizer_ComposedMsgNotSupported(); | ||
} | ||
return abi.encodePacked(_sendParam.dstEid, _sendParam.to, _refundAddress); | ||
} | ||
} |
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 |
---|---|---|
@@ -1,57 +1,110 @@ | ||
pragma solidity 0.8.21; | ||
|
||
import { StrategyBase, Leaf } from "./StrategyBase.t.sol"; | ||
import { LayerZeroOFTDecoderAndSanitizer } from "src/base/DecodersAndSanitizers/LayerZeroOFTDecoderAndSanitizer.sol"; | ||
import { LiveSetup } from "../LiveSetup.t.sol"; | ||
|
||
import { | ||
LayerZeroOFTDecoderAndSanitizer, | ||
BaseDecoderAndSanitizer | ||
} from "src/base/DecodersAndSanitizers/LayerZeroOFTDecoderAndSanitizer.sol"; | ||
import { BoringVault } from "src/base/BoringVault.sol"; | ||
import { IStargate } from "@stargatefinance/stg-evm-v2/src/interfaces/IStargate.sol"; | ||
import { ManagerWithMerkleVerification } from "src/base/Roles/ManagerWithMerkleVerification.sol"; | ||
import { MessagingFee, OFTReceipt, SendParam } from "@layerzerolabs/lz-evm-oapp-v2/contracts/oft/interfaces/IOFT.sol"; | ||
import { ERC20 } from "@solmate/tokens/ERC20.sol"; | ||
import { console } from "@forge-std/Test.sol"; | ||
import { OptionsBuilder } from "@layerzerolabs/lz-evm-oapp-v2/contracts/oapp/libs/OptionsBuilder.sol"; | ||
|
||
address constant ADMIN = 0xF2dE1311C5b2C1BD94de996DA13F80010453e505; | ||
address constant WETH = 0x160345fC359604fC6e70E3c5fAcbdE5F7A9342d8; | ||
address constant STARGATE = 0x5c386D85b1B82FD9Db681b9176C8a4248bb6345B; | ||
uint32 constant ETH_EID = 30_101; | ||
uint256 constant SEI_TO_MINT = 100 ether; | ||
|
||
contract LayerZeroOFTStrategy is StrategyBase, LiveSetup { | ||
uint256 constant ETH_EID = 30_101; | ||
contract LayerZeroOFTStrategy is StrategyBase { | ||
using OptionsBuilder for bytes; | ||
|
||
LayerZeroOFTDecoderAndSanitizer sanitizer; | ||
|
||
function setUp() public override(StrategyBase, LiveSetup) { | ||
LiveSetup.setUp(); | ||
StrategyBase.setUp(); | ||
ManagerWithMerkleVerification manager = ManagerWithMerkleVerification(0x9B99d4584a3858C639F94fE055DB9E94017fE009); | ||
BoringVault boringVault = BoringVault(payable(0x9fAaEA2CDd810b21594E54309DC847842Ae301Ce)); | ||
|
||
function setUp() public override { | ||
uint256 forkId = vm.createFork(vm.envString("L2_RPC_URL")); | ||
vm.selectFork(forkId); | ||
super.setUp(); | ||
} | ||
|
||
function setUpDecoderSanitizers() public override { | ||
sanitizer = new LayerZeroOFTDecoderAndSanitizer(mainConfig.boringVault); | ||
sanitizer = new LayerZeroOFTDecoderAndSanitizer(address(boringVault)); | ||
} | ||
|
||
function testSend() external { | ||
deal(address(boringVault), SEI_TO_MINT); | ||
uint256 amountToSend = ERC20(WETH).balanceOf(address(boringVault)); | ||
console.log(amountToSend); | ||
// owner prank | ||
// deploy sanitizer and build tree | ||
vm.startPrank(mainConfig.protocolAdmin); | ||
bytes memory packedArguments = abi.encodePacked(ETH_EID, address(this)); | ||
Leaf memory myLeaf = Leaf( | ||
address(sanitizer), mainConfig.base, false, LayerZeroOFTDecoderAndSanitizer.send.selector, packedArguments | ||
); | ||
buildExampleTree(myLeaf); | ||
vm.startPrank(ADMIN); | ||
bytes memory packedArguments = abi.encodePacked(STARGATE); | ||
Leaf memory approveLeaf = | ||
Leaf(address(sanitizer), WETH, false, BaseDecoderAndSanitizer.approve.selector, packedArguments); | ||
packedArguments = abi.encodePacked(ETH_EID, addressToBytes32(address(boringVault)), ADMIN); | ||
Leaf memory sendLeaf = | ||
Leaf(address(sanitizer), STARGATE, true, LayerZeroOFTDecoderAndSanitizer.send.selector, packedArguments); | ||
|
||
Leaf[] memory myLeafs = new Leaf[](2); | ||
myLeafs[0] = approveLeaf; | ||
myLeafs[1] = sendLeaf; | ||
buildExampleTree(myLeafs); | ||
|
||
// set leaf in manager | ||
ManagerWithMerkleVerification manager = ManagerWithMerkleVerification(mainConfig.manager); | ||
manager.setManageRoot(mainConfig.strategist, _getRoot()); | ||
ManagerWithMerkleVerification manager = ManagerWithMerkleVerification(manager); | ||
manager.setManageRoot(ADMIN, _getRoot()); | ||
vm.stopPrank(); | ||
|
||
// strategist manages vault | ||
vm.startPrank(mainConfig.strategist); | ||
bytes32[][] memory manageProofs = new bytes32[][](1); | ||
manageProofs[0] = _generateProof(_hashLeaf(myLeaf), tree); | ||
// in this case strategist is also admin | ||
vm.startPrank(ADMIN); | ||
bytes32[][] memory manageProofs = new bytes32[][](2); | ||
manageProofs[0] = _generateProof(_hashLeaf(approveLeaf), tree); | ||
manageProofs[1] = _generateProof(_hashLeaf(sendLeaf), tree); | ||
|
||
address[] memory decodersAndSanitizers = new address[](1); | ||
address[] memory decodersAndSanitizers = new address[](2); | ||
decodersAndSanitizers[0] = address(sanitizer); | ||
decodersAndSanitizers[1] = address(sanitizer); | ||
|
||
address[] memory targets = new address[](2); | ||
targets[0] = WETH; | ||
targets[1] = STARGATE; | ||
|
||
address[] memory targets = new address[](1); | ||
targets[0] = mainConfig.base; | ||
bytes[] memory targetData = new bytes[](2); | ||
targetData[0] = abi.encodeWithSelector(BaseDecoderAndSanitizer.approve.selector, STARGATE, amountToSend); | ||
|
||
bytes[] memory targetData = new bytes[](1); | ||
targetData[0] = abi.encodeWithSelector(LayerZeroOFTDecoderAndSanitizer.send.selector, packedArguments); | ||
bytes memory _extraOptions = OptionsBuilder.newOptions().addExecutorLzReceiveOption(80_000, 0); | ||
SendParam memory sp = SendParam( | ||
ETH_EID, addressToBytes32(address(boringVault)), amountToSend, amountToSend, _extraOptions, "", new bytes(0) | ||
); | ||
|
||
(,, OFTReceipt memory receipt) = IStargate(STARGATE).quoteOFT(sp); | ||
sp.minAmountLD = receipt.amountReceivedLD; | ||
|
||
MessagingFee memory mf = IStargate(STARGATE).quoteSend(sp, false); | ||
uint256 valueToSend = mf.nativeFee; | ||
|
||
uint256[] memory values = new uint256[](1); | ||
targetData[1] = abi.encodeWithSelector(LayerZeroOFTDecoderAndSanitizer.send.selector, sp, mf, ADMIN); | ||
|
||
uint256[] memory values = new uint256[](2); | ||
values[0] = 0; | ||
values[1] = valueToSend; | ||
|
||
manager.manageVaultWithMerkleVerification(manageProofs, decodersAndSanitizers, targets, targetData, values); | ||
console.log("MinAmountLD: ", sp.minAmountLD); | ||
console.log("AmountLD: ", sp.amountLD); | ||
console.log("SEI Spent: ", SEI_TO_MINT - address(boringVault).balance); | ||
console.log("Value to Send: ", valueToSend); | ||
assertEq(ERC20(WETH).balanceOf(address(boringVault)), 0, "Boring Vault should have no more WETH"); | ||
} | ||
|
||
function addressToBytes32(address _addr) public pure returns (bytes32) { | ||
return bytes32(uint256(uint160(_addr))); | ||
} | ||
} |
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,118 @@ | ||
pragma solidity 0.8.21; | ||
|
||
import { StrategyBase, Leaf } from "./StrategyBase.t.sol"; | ||
import { SeiyanEthRebalanceDecoderAndSanitizer } from | ||
"src/base/DecodersAndSanitizers/SeiyanEthRebalanceDecoderAndSanitizer.sol"; | ||
import { NativeWrapperDecoderAndSanitizer } from | ||
"src/base/DecodersAndSanitizers/Protocols/NativeWrapperDecoderAndSanitizer.sol"; | ||
import { PirexEthDecoderAndSanitizer } from "src/base/DecodersAndSanitizers/Protocols/PirexEthDecoderAndSanitizer.sol"; | ||
import { ManagerWithMerkleVerification } from "src/base/Roles/ManagerWithMerkleVerification.sol"; | ||
import { BoringVault } from "src/base/BoringVault.sol"; | ||
import { ERC20 } from "@solmate/tokens/ERC20.sol"; | ||
import { console } from "@forge-std/Test.sol"; | ||
import { Address } from "@openzeppelin/contracts/utils/Address.sol"; | ||
|
||
address constant ADMIN = 0x0000000000417626Ef34D62C4DC189b021603f2F; | ||
address constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; | ||
address constant APX_ETH = 0x9Ba021B0a9b958B5E75cE9f6dff97C7eE52cb3E6; | ||
address constant PIREX_ETH = 0xD664b74274DfEB538d9baC494F3a4760828B02b0; | ||
uint256 constant SEI_WETH = 93.5214859e18; | ||
uint256 constant TARGET_APX_ETH = 235.2211814e18; | ||
|
||
contract SeiyanEthRebalanceStrategyTest is StrategyBase { | ||
using Address for address; | ||
|
||
ERC20 base = ERC20(WETH); | ||
ManagerWithMerkleVerification manager = ManagerWithMerkleVerification(0x9B99d4584a3858C639F94fE055DB9E94017fE009); | ||
BoringVault boringVault = BoringVault(payable(0x9fAaEA2CDd810b21594E54309DC847842Ae301Ce)); | ||
SeiyanEthRebalanceDecoderAndSanitizer decoder; | ||
|
||
function setUp() public override { | ||
uint256 forkId = vm.createFork(vm.envString("L1_RPC_URL")); | ||
vm.selectFork(forkId); | ||
super.setUp(); | ||
} | ||
|
||
function setUpDecoderSanitizers() public override { | ||
decoder = new SeiyanEthRebalanceDecoderAndSanitizer(address(boringVault)); | ||
} | ||
|
||
function testRebalance() public { | ||
// to-do DEAL new WETH that would be bridged | ||
uint256 vaultBalance = base.balanceOf(address(boringVault)); | ||
deal(WETH, address(boringVault), vaultBalance + SEI_WETH); | ||
vaultBalance = base.balanceOf(address(boringVault)); | ||
_setUpManager(vaultBalance); | ||
assertEq(manager.manageRoot(ADMIN), _getRoot(), "Root not set correctly"); | ||
|
||
Leaf[] memory myLeafs = _getLeafsForTest(vaultBalance); | ||
|
||
bytes32[][] memory manageProofs = new bytes32[][](2); | ||
address[] memory decodersAndSanitizers = new address[](2); | ||
address[] memory targets = new address[](2); | ||
bytes[] memory targetData = new bytes[](2); | ||
uint256[] memory values = new uint256[](2); | ||
|
||
manageProofs = _getProofsUsingTree(myLeafs, tree); | ||
decodersAndSanitizers[0] = myLeafs[0].decoderAndSanitizer; | ||
decodersAndSanitizers[1] = myLeafs[1].decoderAndSanitizer; | ||
|
||
targets[0] = myLeafs[0].target; | ||
targets[1] = myLeafs[1].target; | ||
|
||
targetData[0] = abi.encodeWithSelector(myLeafs[0].selector, vaultBalance); | ||
targetData[1] = abi.encodeWithSelector(myLeafs[1].selector, address(boringVault), true); | ||
|
||
values[0] = 0; | ||
values[1] = vaultBalance; | ||
|
||
// console.log("myLeafs[0]"); | ||
// console.log(myLeafs[0].decoderAndSanitizer); | ||
// console.log(myLeafs[0].target); | ||
// console.logBytes(myLeafs[0].packedArgumentAddresses); | ||
// console.logBytes4(myLeafs[0].selector); | ||
// console.log(myLeafs[0].valueNonZero); | ||
// console.log("targetData[0]"); | ||
// console.log(decodersAndSanitizers[0]); | ||
// console.log(targets[0]); | ||
// console.logBytes(targetData[0]); | ||
// console.log(values[0]); | ||
// console.log("As _verifyManageProof"); | ||
// bytes memory vmp_packedArgumentAddresses = | ||
// abi.decode((decodersAndSanitizers[0]).functionStaticCall(targetData[0]), (bytes)); | ||
// console.log(decodersAndSanitizers[0]); | ||
// console.log(targets[0]); | ||
// console.log(values[0]); | ||
// console.logBytes4(bytes4(targetData[0])); | ||
// console.logBytes(vmp_packedArgumentAddresses); | ||
vm.prank(ADMIN); | ||
manager.manageVaultWithMerkleVerification(manageProofs, decodersAndSanitizers, targets, targetData, values); | ||
assertGe(ERC20(APX_ETH).balanceOf(address(boringVault)), TARGET_APX_ETH, "APX_ETH balance is less than target"); | ||
} | ||
|
||
function _setUpManager(uint256 depositAmount) internal { | ||
vm.startPrank(ADMIN); | ||
// admin allows strategy for deposit to APX ETH returning tokens to boring vault | ||
Leaf[] memory myLeafs = _getLeafsForTest(depositAmount); | ||
buildExampleTree(myLeafs); | ||
bytes32 root = _getRoot(); | ||
|
||
manager.setManageRoot(ADMIN, root); | ||
vm.stopPrank(); | ||
} | ||
|
||
function _getLeafsForTest(uint256 depositAmount) internal returns (Leaf[] memory myLeafs) { | ||
// weth -> eth | ||
Leaf memory wethForEthLeaf = | ||
Leaf(address(decoder), WETH, false, NativeWrapperDecoderAndSanitizer.withdraw.selector, ""); | ||
|
||
// eth -> pirexETH for apxETH | ||
bytes memory packedArguments = abi.encodePacked(address(boringVault)); | ||
Leaf memory pirexEthLeaf = | ||
Leaf(address(decoder), PIREX_ETH, true, PirexEthDecoderAndSanitizer.deposit.selector, packedArguments); | ||
myLeafs = new Leaf[](2); | ||
|
||
myLeafs[0] = wethForEthLeaf; | ||
myLeafs[1] = pirexEthLeaf; | ||
} | ||
} |
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