diff --git a/contracts/Retry.sol b/contracts/Retry.sol new file mode 100644 index 00000000..b37293bd --- /dev/null +++ b/contracts/Retry.sol @@ -0,0 +1,24 @@ +// The Licensed Work is (c) 2022 Sygma +// SPDX-License-Identifier: LGPL-3.0-only + +pragma solidity 0.8.11; + +import "@openzeppelin/contracts/access/Ownable.sol"; + +contract Retry is Ownable { + + event Retry(uint8 sourceDomainID, uint8 destinationDomainID, uint256 blockHeight, bytes32 resourceID); + + /** + @notice This method is used to trigger the process for retrying failed deposits on the MPC side. + @notice Only callable by admin. + @param sourceDomainID ID of the retry source. + @param destinationDomainID ID of the transfer destination. + @param blockHeight Block height on origin chain which contains failed deposits. + @param resourceID Resource ID of transfers that are to be retried. + */ + function retry(uint8 sourceDomainID, uint8 destinationDomainID, uint256 blockHeight, bytes32 resourceID) external onlyOwner { + emit Retry(sourceDomainID, destinationDomainID, blockHeight, resourceID); + } + +} \ No newline at end of file diff --git a/test/retry/retry.js b/test/retry/retry.js new file mode 100644 index 00000000..2ffdaf6b --- /dev/null +++ b/test/retry/retry.js @@ -0,0 +1,43 @@ +// The Licensed Work is (c) 2022 Sygma +// SPDX-License-Identifier: LGPL-3.0-only + +const TruffleAssert = require("truffle-assertions"); +const Retry = artifacts.require("Retry") + +contract("Retry", (accounts) => { + let RetryInstance; + + const sourceDomainID = 1; + const destinationDomainID = 2; + const blockHeight = 15; + const resourceID = "0x0000000000000000000000000000000000000000000000000000000000000300"; + + beforeEach(async () => { + RetryInstance = await Retry.new(accounts[0]); + }); + + it("should emit Retry event when retry is called by the owner", async () => { + const tx = await RetryInstance.retry( + sourceDomainID, + destinationDomainID, + blockHeight, + resourceID, + {from: accounts[0]}) + + TruffleAssert.eventEmitted(tx, "Retry", (event) => { + return ( + event.sourceDomainID.toNumber() === sourceDomainID && + event.destinationDomainID.toNumber() === destinationDomainID && + event.blockHeight.toNumber() === blockHeight && + event.resourceID === resourceID + ); + }); + }); + + it("should revert when retry is not called by the owner", async () => { + await TruffleAssert.reverts( + RetryInstance.retry(sourceDomainID, destinationDomainID, blockHeight, resourceID, {from: accounts[1]}), + "Ownable: caller is not the owner." + ) + }); +})