From 93d7024af01d6f9fae2c82c7b7e405107b4172f2 Mon Sep 17 00:00:00 2001 From: Bill Clippy Date: Fri, 21 Jul 2023 00:11:45 -0700 Subject: [PATCH 1/3] Add CrossChainMint Keeper helper --- .../keeper/CrossChainMintKeeperHelper.sol | 76 +++++++++++++++++++ .../keeper/CrossChainSyncKeeperHelper.sol | 4 +- 2 files changed, 78 insertions(+), 2 deletions(-) create mode 100644 contracts/keeper/CrossChainMintKeeperHelper.sol diff --git a/contracts/keeper/CrossChainMintKeeperHelper.sol b/contracts/keeper/CrossChainMintKeeperHelper.sol new file mode 100644 index 00000000..1d773be1 --- /dev/null +++ b/contracts/keeper/CrossChainMintKeeperHelper.sol @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity >=0.6.10 <0.8.0; + +import "@openzeppelin/contracts/access/Ownable.sol"; +import "@chainlink/contracts/src/v0.6/interfaces/KeeperCompatibleInterface.sol"; +import "../layerzero/interfaces/ILayerZeroEndpoint.sol"; + +interface IScheduleRelayer { + function lzEndpoint() external view returns (ILayerZeroEndpoint); + + function subLzChainID() external view returns (uint16); + + function crossChainMint(bytes memory adapterParams) external payable; +} + +contract CrossChainMintKeeperHelper is KeeperCompatibleInterface, Ownable { + uint256 private constant DATA_LENGTH = 32; // abi.encode(uint256) + uint256 private constant MINT_GAS_LIMIT = 100000; + + IScheduleRelayer public immutable relayer; + uint16 public immutable subLzChainID; + ILayerZeroEndpoint public immutable lzEndpoint; + + uint256 public lastTimestamp; + + constructor(address relayer_) public { + relayer = IScheduleRelayer(relayer_); + subLzChainID = IScheduleRelayer(relayer_).subLzChainID(); + lzEndpoint = IScheduleRelayer(relayer_).lzEndpoint(); + _updateLastTimestamp(block.timestamp); + } + + receive() external payable {} + + function withdraw(uint256 value) external onlyOwner { + (bool success, ) = msg.sender.call{value: value}(""); + require(success, "ETH transfer failed"); + } + + function updateLastTimestamp(uint256 lastTimestamp_) external onlyOwner { + _updateLastTimestamp(lastTimestamp_); + } + + function checkUpkeep(bytes calldata) + external + override + returns (bool upkeepNeeded, bytes memory) + { + upkeepNeeded = (block.timestamp > lastTimestamp + 1 weeks); + } + + function performUpkeep(bytes calldata) external override { + uint256 lastTimestamp_ = lastTimestamp; + require(block.timestamp > lastTimestamp_ + 1 weeks, "Not yet"); + + (uint256 srcFees, ) = + lzEndpoint.estimateFees( + subLzChainID, + address(relayer), + new bytes(DATA_LENGTH), + false, + abi.encodePacked(uint16(1), MINT_GAS_LIMIT) + ); + require(address(this).balance >= srcFees, "Not enough balance"); + relayer.crossChainMint{value: srcFees}(abi.encodePacked(uint16(1), MINT_GAS_LIMIT)); + + // Always skip to the lastest week + _updateLastTimestamp( + lastTimestamp_ + ((block.timestamp - lastTimestamp_ - 1) / 1 weeks) * 1 weeks + ); + } + + function _updateLastTimestamp(uint256 lastTimestamp_) private { + lastTimestamp = lastTimestamp_; + } +} diff --git a/contracts/keeper/CrossChainSyncKeeperHelper.sol b/contracts/keeper/CrossChainSyncKeeperHelper.sol index 8f60e1a1..d2b30aaa 100644 --- a/contracts/keeper/CrossChainSyncKeeperHelper.sol +++ b/contracts/keeper/CrossChainSyncKeeperHelper.sol @@ -10,7 +10,7 @@ interface ISubSchedule { function mainLzChainID() external view returns (uint16); - function crossChainSync() external payable; + function crossChainSync(bytes memory adapterParams) external payable; } contract CrossChainSyncKeeperHelper is KeeperCompatibleInterface, Ownable { @@ -62,7 +62,7 @@ contract CrossChainSyncKeeperHelper is KeeperCompatibleInterface, Ownable { abi.encodePacked(uint16(1), SYNC_GAS_LIMIT) ); require(address(this).balance >= srcFees, "Not enough balance"); - subSchedule.crossChainSync{value: srcFees}(); + subSchedule.crossChainSync{value: srcFees}(abi.encodePacked(uint16(1), SYNC_GAS_LIMIT)); // Always skip to the lastest week _updateLastTimestamp( From 3e33a2250cb624500ccff00bfad6019950cee08e Mon Sep 17 00:00:00 2001 From: Bill Clippy Date: Mon, 24 Jul 2023 10:36:14 -0700 Subject: [PATCH 2/3] Check lastWeek in relayer --- .../keeper/CrossChainMintKeeperHelper.sol | 28 +++++-------------- 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/contracts/keeper/CrossChainMintKeeperHelper.sol b/contracts/keeper/CrossChainMintKeeperHelper.sol index 1d773be1..4808d765 100644 --- a/contracts/keeper/CrossChainMintKeeperHelper.sol +++ b/contracts/keeper/CrossChainMintKeeperHelper.sol @@ -4,16 +4,19 @@ pragma solidity >=0.6.10 <0.8.0; import "@openzeppelin/contracts/access/Ownable.sol"; import "@chainlink/contracts/src/v0.6/interfaces/KeeperCompatibleInterface.sol"; import "../layerzero/interfaces/ILayerZeroEndpoint.sol"; +import "../utils/CoreUtility.sol"; interface IScheduleRelayer { function lzEndpoint() external view returns (ILayerZeroEndpoint); function subLzChainID() external view returns (uint16); + function lastWeek() external view returns (uint256); + function crossChainMint(bytes memory adapterParams) external payable; } -contract CrossChainMintKeeperHelper is KeeperCompatibleInterface, Ownable { +contract CrossChainMintKeeperHelper is KeeperCompatibleInterface, Ownable, CoreUtility { uint256 private constant DATA_LENGTH = 32; // abi.encode(uint256) uint256 private constant MINT_GAS_LIMIT = 100000; @@ -21,13 +24,10 @@ contract CrossChainMintKeeperHelper is KeeperCompatibleInterface, Ownable { uint16 public immutable subLzChainID; ILayerZeroEndpoint public immutable lzEndpoint; - uint256 public lastTimestamp; - constructor(address relayer_) public { relayer = IScheduleRelayer(relayer_); subLzChainID = IScheduleRelayer(relayer_).subLzChainID(); lzEndpoint = IScheduleRelayer(relayer_).lzEndpoint(); - _updateLastTimestamp(block.timestamp); } receive() external payable {} @@ -37,22 +37,17 @@ contract CrossChainMintKeeperHelper is KeeperCompatibleInterface, Ownable { require(success, "ETH transfer failed"); } - function updateLastTimestamp(uint256 lastTimestamp_) external onlyOwner { - _updateLastTimestamp(lastTimestamp_); - } - function checkUpkeep(bytes calldata) external override returns (bool upkeepNeeded, bytes memory) { - upkeepNeeded = (block.timestamp > lastTimestamp + 1 weeks); + uint256 startWeek = _endOfWeek(block.timestamp) - 1 weeks; + uint256 lastWeek = relayer.lastWeek(); + upkeepNeeded = (startWeek > lastWeek); } function performUpkeep(bytes calldata) external override { - uint256 lastTimestamp_ = lastTimestamp; - require(block.timestamp > lastTimestamp_ + 1 weeks, "Not yet"); - (uint256 srcFees, ) = lzEndpoint.estimateFees( subLzChainID, @@ -63,14 +58,5 @@ contract CrossChainMintKeeperHelper is KeeperCompatibleInterface, Ownable { ); require(address(this).balance >= srcFees, "Not enough balance"); relayer.crossChainMint{value: srcFees}(abi.encodePacked(uint16(1), MINT_GAS_LIMIT)); - - // Always skip to the lastest week - _updateLastTimestamp( - lastTimestamp_ + ((block.timestamp - lastTimestamp_ - 1) / 1 weeks) * 1 weeks - ); - } - - function _updateLastTimestamp(uint256 lastTimestamp_) private { - lastTimestamp = lastTimestamp_; } } From 468217179fcfe195f2fdf28811fd7eba871f0a06 Mon Sep 17 00:00:00 2001 From: Bill Clippy Date: Mon, 24 Jul 2023 11:14:35 -0700 Subject: [PATCH 3/3] Increase mint gaslimit --- contracts/keeper/CrossChainMintKeeperHelper.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/keeper/CrossChainMintKeeperHelper.sol b/contracts/keeper/CrossChainMintKeeperHelper.sol index 4808d765..57fb286d 100644 --- a/contracts/keeper/CrossChainMintKeeperHelper.sol +++ b/contracts/keeper/CrossChainMintKeeperHelper.sol @@ -18,7 +18,7 @@ interface IScheduleRelayer { contract CrossChainMintKeeperHelper is KeeperCompatibleInterface, Ownable, CoreUtility { uint256 private constant DATA_LENGTH = 32; // abi.encode(uint256) - uint256 private constant MINT_GAS_LIMIT = 100000; + uint256 private constant MINT_GAS_LIMIT = 140000; IScheduleRelayer public immutable relayer; uint16 public immutable subLzChainID;