diff --git a/agent/cli.js b/agent/cli.js index 7ac2729d0..93bf784da 100644 --- a/agent/cli.js +++ b/agent/cli.js @@ -483,6 +483,11 @@ function parse( joExternalHandlers, argv ) { imaState.strChainName_s_chain = joArg.value; continue; } + if( joArg.name == "id-origin-chain" ) { + owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); + imaState.strChainName_origin_chain = joArg.value; + continue; + } if( joArg.name == "id-t-chain" ) { owaspUtils.verifyArgumentWithNonEmptyValue( joArg ); imaState.strChainName_t_chain = joArg.value; diff --git a/agent/main.js b/agent/main.js index 0b37c7ea9..76ff680e0 100644 --- a/agent/main.js +++ b/agent/main.js @@ -120,6 +120,7 @@ global.imaState = { "strChainName_main_net": ( process.env.CHAIN_NAME_ETHEREUM || "Mainnet" ).toString().trim(), "strChainName_s_chain": ( process.env.CHAIN_NAME_SCHAIN || "id-S-chain" ).toString().trim(), + "strChainName_origin_chain": ( process.env.CHAIN_NAME_SCHAIN_ORIGIN || "Mainnet" ).toString().trim(), "strChainName_t_chain": ( process.env.CHAIN_NAME_SCHAIN_TARGET || "id-T-chain" ).toString().trim(), "cid_main_net": owaspUtils.toInteger( process.env.CID_ETHEREUM ) || -4, "cid_s_chain": owaspUtils.toInteger( process.env.CID_SCHAIN ) || -4, @@ -1652,7 +1653,7 @@ if( haveReimbursementCommands ) { } if( imaState.nReimbursementRange >= 0 ) { imaState.arrActions.push( { - "name": "Gas Reimbursement - Set Minimal time interval from S2M transfers", + "name": "Gas Reimbursement - Set Minimal time interval from S2M and S2S transfers", "fn": async function() { await IMA.reimbursement_set_range( imaState.w3_s_chain, @@ -1661,6 +1662,7 @@ if( imaState.nReimbursementRange >= 0 ) { imaState.strChainName_s_chain, imaState.cid_s_chain, imaState.tc_s_chain, + imaState.strChainName_origin_chain, imaState.nReimbursementRange ); return true; diff --git a/npms/skale-ima/index.js b/npms/skale-ima/index.js index 308013118..38c76b818 100644 --- a/npms/skale-ima/index.js +++ b/npms/skale-ima/index.js @@ -2089,6 +2089,7 @@ async function reimbursement_set_range( strChainName_s_chain, cid_s_chain, tc_s_chain, + strChainName_origin_chain, nReimbursementRange ) { const details = log.createMemoryStream(); @@ -2108,6 +2109,7 @@ async function reimbursement_set_range( // const methodWithArguments = jo_community_locker.methods.setTimeLimitPerMessage( // call params, last is destination account on S-chain + strChainName_origin_chain, "0x" + w3_s_chain.utils.toBN( nReimbursementRange ).toString( 16 ) ); const dataTx = methodWithArguments.encodeABI(); // the encoded ABI of the method diff --git a/proxy/contracts/schain/CommunityLocker.sol b/proxy/contracts/schain/CommunityLocker.sol index b853ed679..52683d27d 100644 --- a/proxy/contracts/schain/CommunityLocker.sol +++ b/proxy/contracts/schain/CommunityLocker.sol @@ -28,13 +28,17 @@ import "@skalenetwork/ima-interfaces/schain/ICommunityLocker.sol"; import "../Messages.sol"; +interface ICommunityLockerInitializer is ICommunityLocker { + function initializeTimestamp() external; +} + /** * @title CommunityLocker * @dev Contract contains logic to perform automatic reimbursement * of gas fees for sent messages */ -contract CommunityLocker is ICommunityLocker, AccessControlEnumerableUpgradeable { +contract CommunityLocker is ICommunityLockerInitializer, AccessControlEnumerableUpgradeable { /** * @dev Mainnet identifier. @@ -71,11 +75,11 @@ contract CommunityLocker is ICommunityLocker, AccessControlEnumerableUpgradeable */ bytes32 public schainHash; - /** - * @dev Amount of seconds after message sending - * when next message cannot be sent. - */ - uint public timeLimitPerMessage; + // Disable slither check due to variable depreciation + // and unavailability of making it constant because + // it breaks upgradeability pattern. + // slither-disable-next-line constable-states + uint private _deprecatedTimeLimitPerMessage; /** * @dev Mapping of users who are allowed to send a message. @@ -89,10 +93,30 @@ contract CommunityLocker is ICommunityLocker, AccessControlEnumerableUpgradeable // user address => timestamp of last message mapping(address => uint) public lastMessageTimeStamp; + /** + * @dev mainnet gas price(baseFee) value + */ uint256 public mainnetGasPrice; + /** + * @dev Timestamp of previous set of mainnet gas price + */ uint256 public gasPriceTimestamp; + /** + * @dev Amount of seconds after message sending + * when next message cannot be sent. + */ + // schainHash => time limit + mapping(bytes32 => uint) public timeLimitPerMessage; + + /** + * @dev Timestamp of previous sent message by user during + * schain to schain transfers + */ + // schainHash => user => timestamp + mapping(bytes32 => mapping(address => uint)) public lastMessageTimeStampToSchain; + /** * @dev Emitted when a user becomes active. */ @@ -118,6 +142,19 @@ contract CommunityLocker is ICommunityLocker, AccessControlEnumerableUpgradeable uint newValue ); + modifier checkUserBeforeTransfer(bytes32 chainHash, address user) { + uint256 lastTimestamp = lastMessageTimeStampToSchain[chainHash][user]; + if (chainHash == MAINNET_HASH) { + require(activeUsers[user], "Recipient must be active"); + lastTimestamp = lastMessageTimeStamp[user]; + } + require( + lastTimestamp + timeLimitPerMessage[chainHash] < block.timestamp, + "Exceeded message rate limit" + ); + _; + } + /** * @dev Allows MessageProxy to post operational message from mainnet * or SKALE chains. @@ -163,21 +200,24 @@ contract CommunityLocker is ICommunityLocker, AccessControlEnumerableUpgradeable * - Previous message sent by {receiver} must be sent earlier then {timeLimitPerMessage} seconds before current time * or there are no messages sent by {receiver}. */ - function checkAllowedToSendMessage(address receiver) external override { + function checkAllowedToSendMessage(bytes32 chainHash, address receiver) + external + checkUserBeforeTransfer(chainHash, receiver) + override + { require( tokenManagerLinker.hasTokenManager(ITokenManager(msg.sender)), "Sender is not registered token manager" ); - require(activeUsers[receiver], "Recipient must be active"); - require( - lastMessageTimeStamp[receiver] + timeLimitPerMessage < block.timestamp, - "Trying to send messages too often" - ); - lastMessageTimeStamp[receiver] = block.timestamp; + if (chainHash == MAINNET_HASH) { + lastMessageTimeStamp[receiver] = block.timestamp; + } else { + lastMessageTimeStampToSchain[chainHash][receiver] = block.timestamp; + } } /** - * @dev Set value of {timeLimitPerMessage}. + * @dev Set value of {timeLimitPerMessage} of given chain. * * Requirements: * @@ -185,14 +225,16 @@ contract CommunityLocker is ICommunityLocker, AccessControlEnumerableUpgradeable * * Emits a {ConstantUpdated} event. */ - function setTimeLimitPerMessage(uint newTimeLimitPerMessage) external override { + function setTimeLimitPerMessage(string memory chainName, uint newTimeLimitPerMessage) external override { require(hasRole(CONSTANT_SETTER_ROLE, msg.sender), "Not enough permissions to set constant"); + bytes32 chainHash = keccak256(abi.encodePacked(chainName)); + require(chainHash != schainHash, "Incorrect chain"); emit ConstantUpdated( keccak256(abi.encodePacked("TimeLimitPerMessage")), - timeLimitPerMessage, + timeLimitPerMessage[chainHash], newTimeLimitPerMessage ); - timeLimitPerMessage = newTimeLimitPerMessage; + timeLimitPerMessage[chainHash] = newTimeLimitPerMessage; } /** @@ -247,7 +289,21 @@ contract CommunityLocker is ICommunityLocker, AccessControlEnumerableUpgradeable messageProxy = newMessageProxy; tokenManagerLinker = newTokenManagerLinker; schainHash = keccak256(abi.encodePacked(newSchainName)); - timeLimitPerMessage = 5 minutes; + timeLimitPerMessage[MAINNET_HASH] = 5 minutes; communityPool = newCommunityPool; } + + /** + * @dev Initialize timestamp after upgrade and should be removed after upgrade + * + * Requirements: + * Should be called only by address which hold DEFAULT_ADMIN_ROLE role + */ + function initializeTimestamp() external override { + require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), "Incorrect sender"); + // Disable slither check due to moving data to the new data structure + // slither-disable-next-line uninitialized-state + timeLimitPerMessage[MAINNET_HASH] = _deprecatedTimeLimitPerMessage; + delete _deprecatedTimeLimitPerMessage; + } } diff --git a/proxy/contracts/schain/TokenManagers/TokenManagerERC1155.sol b/proxy/contracts/schain/TokenManagers/TokenManagerERC1155.sol index dc463d18b..ae7e62ae8 100644 --- a/proxy/contracts/schain/TokenManagers/TokenManagerERC1155.sol +++ b/proxy/contracts/schain/TokenManagers/TokenManagerERC1155.sol @@ -111,7 +111,7 @@ contract TokenManagerERC1155 is external override { - communityLocker.checkAllowedToSendMessage(msg.sender); + communityLocker.checkAllowedToSendMessage(MAINNET_HASH, msg.sender); _exit(MAINNET_HASH, depositBox, contractOnMainnet, msg.sender, id, amount); } @@ -128,7 +128,7 @@ contract TokenManagerERC1155 is external override { - communityLocker.checkAllowedToSendMessage(msg.sender); + communityLocker.checkAllowedToSendMessage(MAINNET_HASH, msg.sender); _exitBatch(MAINNET_HASH, depositBox, contractOnMainnet, msg.sender, ids, amounts); } @@ -149,6 +149,7 @@ contract TokenManagerERC1155 is rightTransaction(targetSchainName, msg.sender) { bytes32 targetSchainHash = keccak256(abi.encodePacked(targetSchainName)); + communityLocker.checkAllowedToSendMessage(targetSchainHash, msg.sender); _exit(targetSchainHash, tokenManagers[targetSchainHash], contractOnMainnet, msg.sender, id, amount); } @@ -169,6 +170,7 @@ contract TokenManagerERC1155 is rightTransaction(targetSchainName, msg.sender) { bytes32 targetSchainHash = keccak256(abi.encodePacked(targetSchainName)); + communityLocker.checkAllowedToSendMessage(targetSchainHash, msg.sender); _exitBatch(targetSchainHash, tokenManagers[targetSchainHash], contractOnMainnet, msg.sender, ids, amounts); } diff --git a/proxy/contracts/schain/TokenManagers/TokenManagerERC20.sol b/proxy/contracts/schain/TokenManagers/TokenManagerERC20.sol index 6d72b1fdb..a502b90fd 100644 --- a/proxy/contracts/schain/TokenManagers/TokenManagerERC20.sol +++ b/proxy/contracts/schain/TokenManagers/TokenManagerERC20.sol @@ -99,7 +99,7 @@ contract TokenManagerERC20 is TokenManager, ITokenManagerERC20 { external override { - communityLocker.checkAllowedToSendMessage(msg.sender); + communityLocker.checkAllowedToSendMessage(MAINNET_HASH, msg.sender); _exit(MAINNET_HASH, depositBox, contractOnMainnet, msg.sender, amount); } @@ -119,6 +119,7 @@ contract TokenManagerERC20 is TokenManager, ITokenManagerERC20 { rightTransaction(targetSchainName, msg.sender) { bytes32 targetSchainHash = keccak256(abi.encodePacked(targetSchainName)); + communityLocker.checkAllowedToSendMessage(targetSchainHash, msg.sender); _exit(targetSchainHash, tokenManagers[targetSchainHash], contractOnMainnet, msg.sender, amount); } diff --git a/proxy/contracts/schain/TokenManagers/TokenManagerERC721.sol b/proxy/contracts/schain/TokenManagers/TokenManagerERC721.sol index 3f815e833..34c6fe4ee 100644 --- a/proxy/contracts/schain/TokenManagers/TokenManagerERC721.sol +++ b/proxy/contracts/schain/TokenManagers/TokenManagerERC721.sol @@ -98,7 +98,7 @@ contract TokenManagerERC721 is TokenManager, ITokenManagerERC721 { external override { - communityLocker.checkAllowedToSendMessage(msg.sender); + communityLocker.checkAllowedToSendMessage(MAINNET_HASH, msg.sender); _exit(MAINNET_HASH, depositBox, contractOnMainnet, msg.sender, tokenId); } @@ -118,6 +118,7 @@ contract TokenManagerERC721 is TokenManager, ITokenManagerERC721 { rightTransaction(targetSchainName, msg.sender) { bytes32 targetSchainHash = keccak256(abi.encodePacked(targetSchainName)); + communityLocker.checkAllowedToSendMessage(targetSchainHash, msg.sender); _exit(targetSchainHash, tokenManagers[targetSchainHash], contractOnMainnet, msg.sender, tokenId); } diff --git a/proxy/contracts/schain/TokenManagers/TokenManagerEth.sol b/proxy/contracts/schain/TokenManagers/TokenManagerEth.sol index 28f3aaf03..56fe9565e 100644 --- a/proxy/contracts/schain/TokenManagers/TokenManagerEth.sol +++ b/proxy/contracts/schain/TokenManagers/TokenManagerEth.sol @@ -54,7 +54,7 @@ contract TokenManagerEth is TokenManager, ITokenManagerEth { * EthErc20 tokens are burned on schain and ETH are unlocked on mainnet for {to} address. */ function exitToMain(uint256 amount) external override { - communityLocker.checkAllowedToSendMessage(msg.sender); + communityLocker.checkAllowedToSendMessage(MAINNET_HASH, msg.sender); _exit(MAINNET_HASH, depositBox, msg.sender, amount); } diff --git a/proxy/migrations/upgradeSchain.ts b/proxy/migrations/upgradeSchain.ts index f54d9a7f7..3f4438a42 100644 --- a/proxy/migrations/upgradeSchain.ts +++ b/proxy/migrations/upgradeSchain.ts @@ -1,6 +1,11 @@ -import { contracts } from "./deploySchain"; +import { getManifestAdmin } from "@openzeppelin/hardhat-upgrades/dist/admin"; +import { CommunityLocker } from "../typechain/CommunityLocker"; +import { contracts, getContractKeyInAbiFile } from "./deploySchain"; import { manifestSetup } from "./generateManifest"; +import { encodeTransaction } from "./tools/multiSend"; import { upgrade } from "./upgrade"; +import chalk from "chalk"; +import { ethers } from "hardhat"; function stringValue(value: string | undefined) { if (value) { @@ -20,7 +25,24 @@ async function main() { // deploying of new contracts }, async( safeTransactions, abi ) => { - // initialization + const communityLockerName = "CommunityLocker"; + const communityLockerFactory = await ethers.getContractFactory(communityLockerName); + const communityLockerAddress = abi[getContractKeyInAbiFile(communityLockerName) + "_address"]; + let communityLocker; + if (communityLockerAddress) { + communityLocker = communityLockerFactory.attach(communityLockerAddress) as CommunityLocker; + console.log(chalk.yellow("Prepare transaction to initialize timestamp")); + safeTransactions.push(encodeTransaction( + 0, + communityLockerAddress, + 0, + communityLocker.interface.encodeFunctionData("initializeTimestamp") + )); + } else { + console.log(chalk.red("CommunityLocker was not found!")); + console.log(chalk.red("Check your abi!!!")); + process.exit(1); + } }, "proxySchain" ); diff --git a/proxy/package.json b/proxy/package.json index 662746b12..fd7126b2f 100644 --- a/proxy/package.json +++ b/proxy/package.json @@ -26,7 +26,7 @@ "@openzeppelin/contracts-upgradeable": "^4.7.1", "@openzeppelin/hardhat-upgrades": "^1.9.0", "@skalenetwork/etherbase-interfaces": "^0.0.1-develop.20", - "@skalenetwork/ima-interfaces": "1.0.0-develop.22", + "@skalenetwork/ima-interfaces": "1.0.0-develop.23", "@skalenetwork/skale-manager-interfaces": "1.0.0", "axios": "^0.21.4", "dotenv": "^10.0.0", diff --git a/proxy/predeployed/src/ima_predeployed/contracts/community_locker.py b/proxy/predeployed/src/ima_predeployed/contracts/community_locker.py index 850d40944..9dff37b2c 100644 --- a/proxy/predeployed/src/ima_predeployed/contracts/community_locker.py +++ b/proxy/predeployed/src/ima_predeployed/contracts/community_locker.py @@ -15,6 +15,7 @@ class CommunityLockerGenerator(AccessControlEnumerableGenerator): META_FILENAME = 'CommunityLocker.meta.json' DEFAULT_ADMIN_ROLE = (0).to_bytes(32, 'big') DEFAULT_TIME_LIMIT_SEC = 5 * 60 + MAINNET_HASH = Web3.solidityKeccak(['string'], ['Mainnet']) # ---------- storage ---------- # --------Initializable-------- @@ -42,9 +43,13 @@ class CommunityLockerGenerator(AccessControlEnumerableGenerator): # 202: tokenManagerLinker # 203: communityPool # 204: schainHash - # 205: timeLimitPerMessage - # 206: _unfrozenUsers - # 207: _lastMessageTimeStamp + # 205: _deprecatedTimeLimitPerMessage + # 206: activeUsers + # 207: lastMessageTimeStamp + # 208: mainnetGasPrice + # 209: gasPriceTimestamp + # 210: timeLimitPerMessage + # 211: lastMessageTimeStampToSchain INITIALIZED_SLOT = 0 ROLES_SLOT = 101 @@ -53,7 +58,7 @@ class CommunityLockerGenerator(AccessControlEnumerableGenerator): TOKEN_MANAGER_LINKER_SLOT = AccessControlEnumerableGenerator.next_slot(MESSAGE_PROXY_SLOT) COMMUNITY_POOL_SLOT = AccessControlEnumerableGenerator.next_slot(TOKEN_MANAGER_LINKER_SLOT) SCHAIN_HASH_SLOT = AccessControlEnumerableGenerator.next_slot(COMMUNITY_POOL_SLOT) - TIME_LIMIT_PER_MESSAGE_SLOT = AccessControlEnumerableGenerator.next_slot(SCHAIN_HASH_SLOT) + TIME_LIMIT_PER_MESSAGE_SLOT = 210 def __init__(self): generator = CommunityLockerGenerator.from_hardhat_artifact( @@ -77,7 +82,9 @@ def generate_storage(cls, **kwargs) -> Dict[str, str]: cls._write_address(storage, cls.COMMUNITY_POOL_SLOT, community_pool_address) cls._write_bytes32(storage, cls.SCHAIN_HASH_SLOT, Web3.solidityKeccak(['string'], [schain_name])) - cls._write_uint256(storage, cls.TIME_LIMIT_PER_MESSAGE_SLOT, cls.DEFAULT_TIME_LIMIT_SEC) + time_limit_per_message_slot = AccessControlEnumerableGenerator.calculate_mapping_value_slot( + cls.TIME_LIMIT_PER_MESSAGE_SLOT, cls.MAINNET_HASH, 'bytes32') + cls._write_uint256(storage, time_limit_per_message_slot, cls.DEFAULT_TIME_LIMIT_SEC) return storage diff --git a/proxy/predeployed/test/contracts/community_locker.py b/proxy/predeployed/test/contracts/community_locker.py index e5a53eb86..a1707e98b 100644 --- a/proxy/predeployed/test/contracts/community_locker.py +++ b/proxy/predeployed/test/contracts/community_locker.py @@ -14,4 +14,4 @@ def check_community_locker(deployer_address: str, schain_name: str, community_po if not community_locker.functions.tokenManagerLinker().call() == TOKEN_MANAGER_LINKER_ADDRESS: raise AssertionError if not community_locker.functions.communityPool().call() == community_pool_address: raise AssertionError if not community_locker.functions.schainHash().call() == w3.solidityKeccak(['string'], [schain_name]): raise AssertionError - if not community_locker.functions.timeLimitPerMessage().call() == CommunityLockerGenerator.DEFAULT_TIME_LIMIT_SEC: raise AssertionError + if not community_locker.functions.timeLimitPerMessage(CommunityLockerGenerator.MAINNET_HASH).call() == CommunityLockerGenerator.DEFAULT_TIME_LIMIT_SEC: raise AssertionError diff --git a/proxy/test/CommunityLocker.ts b/proxy/test/CommunityLocker.ts index 9d75f5913..23d3f62d4 100644 --- a/proxy/test/CommunityLocker.ts +++ b/proxy/test/CommunityLocker.ts @@ -107,11 +107,25 @@ describe("CommunityLocker", () => { }); it("should set time limit per message", async () => { - await communityLocker.setTimeLimitPerMessage(0) + expect(await communityLocker.timeLimitPerMessage(mainnetHash)).to.be.equal(300); + await communityLocker.setTimeLimitPerMessage("Mainnet", 0) .should.be.eventually.rejectedWith("Not enough permissions to set constant"); await communityLocker.grantRole(await communityLocker.CONSTANT_SETTER_ROLE(), deployer.address); - await communityLocker.setTimeLimitPerMessage(0); - expect(BigNumber.from(await communityLocker.timeLimitPerMessage()).toString()).to.be.equal(BigNumber.from(0).toString()); + await communityLocker.setTimeLimitPerMessage("Mainnet", 0); + expect(await communityLocker.timeLimitPerMessage(mainnetHash)).to.be.equal(0); + }); + + it("should set time limit per message for schain", async () => { + const anotherSchainName = "Schain Sierra"; + const schainHash = ethers.utils.id(anotherSchainName); + expect(await communityLocker.timeLimitPerMessage(schainHash)).to.be.equal(0); + await communityLocker.setTimeLimitPerMessage(anotherSchainName, 1200) + .should.be.eventually.rejectedWith("Not enough permissions to set constant"); + await communityLocker.grantRole(await communityLocker.CONSTANT_SETTER_ROLE(), deployer.address); + await communityLocker.setTimeLimitPerMessage(schainName, 1200) + .should.be.eventually.rejectedWith("Incorrect chain"); + await communityLocker.setTimeLimitPerMessage(anotherSchainName, 1200); + expect(await communityLocker.timeLimitPerMessage(schainHash)).to.be.equal(1200); }); it("should set gasprice", async () => { @@ -128,8 +142,8 @@ describe("CommunityLocker", () => { const time = await currentTime(); await communityLocker.setGasPrice(100, time + 200, sign).should.be.eventually.rejectedWith("Timestamp should not be in the future"); await communityLocker.setGasPrice(100, time, sign); - expect(BigNumber.from(await communityLocker.mainnetGasPrice()).toString()).to.be.equal(BigNumber.from(100).toString()); - expect(BigNumber.from(await communityLocker.gasPriceTimestamp()).toString()).to.be.equal(BigNumber.from(time).toString()); + expect(await communityLocker.mainnetGasPrice()).to.be.equal(100); + expect(await communityLocker.gasPriceTimestamp()).to.be.equal(time); skipTime(60); @@ -137,7 +151,7 @@ describe("CommunityLocker", () => { await communityLocker.setGasPrice(101, time, sign).should.be.eventually.rejectedWith("Gas price timestamp already updated"); await communityLocker.setGasPrice(101, time + 70, sign).should.be.eventually.rejectedWith("Timestamp should not be in the future"); await communityLocker.setGasPrice(101, time + 40, sign); - expect(BigNumber.from(await communityLocker.mainnetGasPrice()).toString()).to.be.equal(BigNumber.from(101).toString()); - expect(BigNumber.from(await communityLocker.gasPriceTimestamp()).toString()).to.be.equal(BigNumber.from(time + 40).toString()); + expect(await communityLocker.mainnetGasPrice()).to.be.equal(101); + expect(await communityLocker.gasPriceTimestamp()).to.be.equal(time + 40); }); }); diff --git a/proxy/test/TokenManagerERC1155.ts b/proxy/test/TokenManagerERC1155.ts index 18e46ca82..92b3425ae 100644 --- a/proxy/test/TokenManagerERC1155.ts +++ b/proxy/test/TokenManagerERC1155.ts @@ -35,6 +35,7 @@ import { } from "../typechain"; import { randomString, stringValue } from "./utils/helper"; +import { skipTime } from "./utils/time"; chai.should(); chai.use((chaiAsPromised as any)); @@ -248,6 +249,93 @@ describe("TokenManagerERC1155", () => { outgoingMessagesCounter.should.be.deep.equal(BigNumber.from(1)); }); + it("should reject `transferToSchainERC1155` when executing earlier then allowed", async () => { + // add connected chain: + await messageProxyForSchain.connect(deployer).grantRole(await messageProxyForSchain.CHAIN_CONNECTOR_ROLE(), deployer.address); + await messageProxyForSchain.connect(deployer).addConnectedChain(newSchainName); + + await erc1155OnOriginChain.connect(deployer).mint(user.address, id, 5, "0x"); + await erc1155OnOriginChain.connect(user).setApprovalForAll(tokenManagerERC1155.address, true); + + await tokenManagerERC1155 + .connect(user) + .transferToSchainERC1155(newSchainName, erc1155OnOriginChain.address, id, 1) + .should.be.eventually.rejectedWith("Incorrect Token Manager address"); + + await tokenManagerERC1155 + .connect(user) + .transferToSchainERC1155("Mainnet", erc1155OnOriginChain.address, id, 1) + .should.be.eventually.rejectedWith("This function is not for transferring to Mainnet"); + + await tokenManagerERC1155.addTokenManager(newSchainName, tokenManagerERC11552.address); + + await tokenManagerERC1155 + .connect(user) + .transferToSchainERC1155(newSchainName, erc1155OnOriginChain.address, id, 1); + + BigNumber.from(await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName)).should.be.deep.equal(BigNumber.from(1)); + + + await tokenManagerERC1155 + .connect(user) + .transferToSchainERC1155(newSchainName, erc1155OnOriginChain.address, id, 1); + + BigNumber.from(await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName)).should.be.deep.equal(BigNumber.from(2)); + + await communityLocker.grantRole(await communityLocker.CONSTANT_SETTER_ROLE(), deployer.address); + + await communityLocker.setTimeLimitPerMessage(newSchainName, 100); + + await tokenManagerERC1155 + .connect(user) + .transferToSchainERC1155(newSchainName, erc1155OnOriginChain.address, id, 1) + .should.be.eventually.rejectedWith("Exceeded message rate limit"); + + BigNumber.from(await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName)).should.be.deep.equal(BigNumber.from(2)); + + await skipTime(90); + + await tokenManagerERC1155 + .connect(user) + .transferToSchainERC1155(newSchainName, erc1155OnOriginChain.address, id, 1) + .should.be.eventually.rejectedWith("Exceeded message rate limit"); + + BigNumber.from(await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName)).should.be.deep.equal(BigNumber.from(2)); + + await skipTime(20); + + await tokenManagerERC1155 + .connect(user) + .transferToSchainERC1155(newSchainName, erc1155OnOriginChain.address, id, 1); + + BigNumber.from(await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName)).should.be.deep.equal(BigNumber.from(3)); + + await communityLocker.setTimeLimitPerMessage(newSchainName, 0); + + await tokenManagerERC1155 + .connect(user) + .transferToSchainERC1155(newSchainName, erc1155OnOriginChain.address, id, 1); + + BigNumber.from(await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName)).should.be.deep.equal(BigNumber.from(4)); + + await communityLocker.setTimeLimitPerMessage(newSchainName, 100); + + await tokenManagerERC1155 + .connect(user) + .transferToSchainERC1155(newSchainName, erc1155OnOriginChain.address, id, 1) + .should.be.eventually.rejectedWith("Exceeded message rate limit"); + + BigNumber.from(await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName)).should.be.deep.equal(BigNumber.from(4)); + + await skipTime(110); + + await tokenManagerERC1155 + .connect(user) + .transferToSchainERC1155(newSchainName, erc1155OnOriginChain.address, id, 1); + + BigNumber.from(await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName)).should.be.deep.equal(BigNumber.from(5)); + }); + it("should invoke `transferToSchainERC1155` and receive tokens without mistakes", async () => { // add connected chain: await messageProxyForSchain.connect(deployer).grantRole(await messageProxyForSchain.CHAIN_CONNECTOR_ROLE(), deployer.address); @@ -1203,6 +1291,93 @@ describe("TokenManagerERC1155", () => { outgoingMessagesCounter.should.be.deep.equal(BigNumber.from(1)); }); + it("should reject `transferToSchainERC1155` when executing earlier then allowed", async () => { + // add connected chain: + await messageProxyForSchain.connect(deployer).grantRole(await messageProxyForSchain.CHAIN_CONNECTOR_ROLE(), deployer.address); + await messageProxyForSchain.connect(deployer).addConnectedChain(newSchainName); + + await erc1155OnOriginChain.connect(deployer).mintBatch(user.address, ids, [5, 5, 5, 5], "0x"); + await erc1155OnOriginChain.connect(user).setApprovalForAll(tokenManagerERC1155.address, true); + + await tokenManagerERC1155 + .connect(user) + .transferToSchainERC1155Batch(newSchainName, erc1155OnOriginChain.address, ids, [1, 1, 1, 1]) + .should.be.eventually.rejectedWith("Incorrect Token Manager address"); + + await tokenManagerERC1155 + .connect(user) + .transferToSchainERC1155Batch("Mainnet", erc1155OnOriginChain.address, ids, [1, 1, 1, 1]) + .should.be.eventually.rejectedWith("This function is not for transferring to Mainnet"); + + await tokenManagerERC1155.addTokenManager(newSchainName, tokenManagerERC11552.address); + + await tokenManagerERC1155 + .connect(user) + .transferToSchainERC1155Batch(newSchainName, erc1155OnOriginChain.address, ids, [1, 1, 1, 1]); + + BigNumber.from(await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName)).should.be.deep.equal(BigNumber.from(1)); + + + await tokenManagerERC1155 + .connect(user) + .transferToSchainERC1155Batch(newSchainName, erc1155OnOriginChain.address, ids, [1, 1, 1, 1]); + + BigNumber.from(await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName)).should.be.deep.equal(BigNumber.from(2)); + + await communityLocker.grantRole(await communityLocker.CONSTANT_SETTER_ROLE(), deployer.address); + + await communityLocker.setTimeLimitPerMessage(newSchainName, 100); + + await tokenManagerERC1155 + .connect(user) + .transferToSchainERC1155Batch(newSchainName, erc1155OnOriginChain.address, ids, [1, 1, 1, 1]) + .should.be.eventually.rejectedWith("Exceeded message rate limit"); + + BigNumber.from(await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName)).should.be.deep.equal(BigNumber.from(2)); + + await skipTime(90); + + await tokenManagerERC1155 + .connect(user) + .transferToSchainERC1155Batch(newSchainName, erc1155OnOriginChain.address, ids, [1, 1, 1, 1]) + .should.be.eventually.rejectedWith("Exceeded message rate limit"); + + BigNumber.from(await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName)).should.be.deep.equal(BigNumber.from(2)); + + await skipTime(20); + + await tokenManagerERC1155 + .connect(user) + .transferToSchainERC1155Batch(newSchainName, erc1155OnOriginChain.address, ids, [1, 1, 1, 1]); + + BigNumber.from(await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName)).should.be.deep.equal(BigNumber.from(3)); + + await communityLocker.setTimeLimitPerMessage(newSchainName, 0); + + await tokenManagerERC1155 + .connect(user) + .transferToSchainERC1155Batch(newSchainName, erc1155OnOriginChain.address, ids, [1, 1, 1, 1]); + + BigNumber.from(await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName)).should.be.deep.equal(BigNumber.from(4)); + + await communityLocker.setTimeLimitPerMessage(newSchainName, 100); + + await tokenManagerERC1155 + .connect(user) + .transferToSchainERC1155Batch(newSchainName, erc1155OnOriginChain.address, ids, [1, 1, 1, 1]) + .should.be.eventually.rejectedWith("Exceeded message rate limit"); + + BigNumber.from(await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName)).should.be.deep.equal(BigNumber.from(4)); + + await skipTime(110); + + await tokenManagerERC1155 + .connect(user) + .transferToSchainERC1155Batch(newSchainName, erc1155OnOriginChain.address, ids, [1, 1, 1, 1]); + + BigNumber.from(await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName)).should.be.deep.equal(BigNumber.from(5)); + }); + it("should invoke `transferToSchainERC1155` and receive tokens without mistakes", async () => { // add connected chain: await messageProxyForSchain.connect(deployer).grantRole(await messageProxyForSchain.CHAIN_CONNECTOR_ROLE(), deployer.address); diff --git a/proxy/test/TokenManagerERC20.ts b/proxy/test/TokenManagerERC20.ts index 2e327d982..9058e1c3a 100644 --- a/proxy/test/TokenManagerERC20.ts +++ b/proxy/test/TokenManagerERC20.ts @@ -52,6 +52,7 @@ import { BigNumber } from "ethers"; import { assert, expect } from "chai"; import { deployKeyStorageMock } from "./utils/deploy/test/keyStorageMock"; +import { skipTime } from "./utils/time"; describe("TokenManagerERC20", () => { let deployer: SignerWithAddress; @@ -304,6 +305,107 @@ describe("TokenManagerERC20", () => { outgoingMessagesCounter.should.be.deep.equal(BigNumber.from(1)); }); + it("should reject `transferToSchainERC20` when executing earlier then allowed", async () => { + const amount = "20000000000000000"; + await messageProxyForSchain.registerExtraContract(newSchainName, tokenManagerErc20.address); + + // add connected chain: + await messageProxyForSchain.connect(deployer).grantRole(await messageProxyForSchain.CHAIN_CONNECTOR_ROLE(), deployer.address); + await messageProxyForSchain.connect(deployer).addConnectedChain(newSchainName); + + await erc20OnOriginChain.connect(deployer).mint(user.address, amount); + await erc20OnOriginChain.connect(user).approve(tokenManagerErc20.address, amount); + + await tokenManagerErc20 + .connect(user) + .transferToSchainERC20(newSchainName, erc20OnOriginChain.address, amount) + .should.be.eventually.rejectedWith("Incorrect Token Manager address"); + + await tokenManagerErc20 + .connect(user) + .transferToSchainERC20("Mainnet", erc20OnOriginChain.address, amount) + .should.be.eventually.rejectedWith("This function is not for transferring to Mainnet"); + + await tokenManagerErc20.addTokenManager(newSchainName, tokenManagerErc202.address); + + await tokenManagerErc20 + .connect(user) + .transferToSchainERC20(newSchainName, erc20OnOriginChain.address, amount); + + BigNumber.from(await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName)).should.be.deep.equal(BigNumber.from(1)); + + await erc20OnOriginChain.connect(deployer).mint(user.address, amount); + await erc20OnOriginChain.connect(user).approve(tokenManagerErc20.address, amount); + + await tokenManagerErc20 + .connect(user) + .transferToSchainERC20(newSchainName, erc20OnOriginChain.address, amount); + + BigNumber.from(await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName)).should.be.deep.equal(BigNumber.from(2)); + + await communityLocker.grantRole(await communityLocker.CONSTANT_SETTER_ROLE(), deployer.address); + + await communityLocker.setTimeLimitPerMessage(newSchainName, 100); + + await erc20OnOriginChain.connect(deployer).mint(user.address, amount); + await erc20OnOriginChain.connect(user).approve(tokenManagerErc20.address, amount); + + await tokenManagerErc20 + .connect(user) + .transferToSchainERC20(newSchainName, erc20OnOriginChain.address, amount) + .should.be.eventually.rejectedWith("Exceeded message rate limit"); + + BigNumber.from(await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName)).should.be.deep.equal(BigNumber.from(2)); + + await skipTime(90); + + await tokenManagerErc20 + .connect(user) + .transferToSchainERC20(newSchainName, erc20OnOriginChain.address, amount) + .should.be.eventually.rejectedWith("Exceeded message rate limit"); + + BigNumber.from(await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName)).should.be.deep.equal(BigNumber.from(2)); + + await skipTime(20); + + await tokenManagerErc20 + .connect(user) + .transferToSchainERC20(newSchainName, erc20OnOriginChain.address, amount); + + BigNumber.from(await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName)).should.be.deep.equal(BigNumber.from(3)); + + await communityLocker.setTimeLimitPerMessage(newSchainName, 0); + + await erc20OnOriginChain.connect(deployer).mint(user.address, amount); + await erc20OnOriginChain.connect(user).approve(tokenManagerErc20.address, amount); + + await tokenManagerErc20 + .connect(user) + .transferToSchainERC20(newSchainName, erc20OnOriginChain.address, amount); + + BigNumber.from(await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName)).should.be.deep.equal(BigNumber.from(4)); + + await communityLocker.setTimeLimitPerMessage(newSchainName, 100); + + await erc20OnOriginChain.connect(deployer).mint(user.address, amount); + await erc20OnOriginChain.connect(user).approve(tokenManagerErc20.address, amount); + + await tokenManagerErc20 + .connect(user) + .transferToSchainERC20(newSchainName, erc20OnOriginChain.address, amount) + .should.be.eventually.rejectedWith("Exceeded message rate limit"); + + BigNumber.from(await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName)).should.be.deep.equal(BigNumber.from(4)); + + await skipTime(110); + + await tokenManagerErc20 + .connect(user) + .transferToSchainERC20(newSchainName, erc20OnOriginChain.address, amount); + + BigNumber.from(await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName)).should.be.deep.equal(BigNumber.from(5)); + }); + it("should invoke `transferToSchainERC20` and receive tokens without mistakes", async () => { const amount = "20000000000000000"; await messageProxyForSchain.registerExtraContract(newSchainName, tokenManagerErc20.address); diff --git a/proxy/test/TokenManagerERC721.ts b/proxy/test/TokenManagerERC721.ts index 19cc6971e..29190ef7c 100644 --- a/proxy/test/TokenManagerERC721.ts +++ b/proxy/test/TokenManagerERC721.ts @@ -35,6 +35,7 @@ import { } from "../typechain"; import { randomString, stringValue } from "./utils/helper"; +import { skipTime } from "./utils/time"; chai.should(); chai.use((chaiAsPromised as any)); @@ -120,7 +121,7 @@ describe("TokenManagerERC721", () => { await messageProxyForSchain.connect(deployer).grantRole(extraContractRegistrarRole, deployer.address); await communityLocker.grantRole(await communityLocker.CONSTANT_SETTER_ROLE(), deployer.address); - await communityLocker.setTimeLimitPerMessage(0); + await communityLocker.setTimeLimitPerMessage("Mainnet", 0); }); it("should change depositBox address", async () => { @@ -259,6 +260,106 @@ describe("TokenManagerERC721", () => { outgoingMessagesCounter.should.be.deep.equal(BigNumber.from(1)); }); + it("should reject `transferToSchainERC721` when executing earlier then allowed", async () => { + await messageProxyForSchain.registerExtraContract(newSchainName, tokenManagerERC721.address); + + // add connected chain: + await messageProxyForSchain.connect(deployer).grantRole(await messageProxyForSchain.CHAIN_CONNECTOR_ROLE(), deployer.address); + await messageProxyForSchain.connect(deployer).addConnectedChain(newSchainName); + + await erc721OnOriginChain.connect(deployer).mint(user.address, 1); + await erc721OnOriginChain.connect(user).approve(tokenManagerERC721.address, 1); + + await tokenManagerERC721 + .connect(user) + .transferToSchainERC721(newSchainName, erc721OnOriginChain.address, 1) + .should.be.eventually.rejectedWith("Incorrect Token Manager address"); + + await tokenManagerERC721 + .connect(user) + .transferToSchainERC721("Mainnet", erc721OnOriginChain.address, 1) + .should.be.eventually.rejectedWith("This function is not for transferring to Mainnet"); + + await tokenManagerERC721.addTokenManager(newSchainName, tokenManagerERC7212.address); + + await tokenManagerERC721 + .connect(user) + .transferToSchainERC721(newSchainName, erc721OnOriginChain.address, 1); + + BigNumber.from(await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName)).should.be.deep.equal(BigNumber.from(1)); + + await erc721OnOriginChain.connect(deployer).mint(user.address, 2); + await erc721OnOriginChain.connect(user).approve(tokenManagerERC721.address, 2); + + await tokenManagerERC721 + .connect(user) + .transferToSchainERC721(newSchainName, erc721OnOriginChain.address, 2); + + BigNumber.from(await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName)).should.be.deep.equal(BigNumber.from(2)); + + await communityLocker.grantRole(await communityLocker.CONSTANT_SETTER_ROLE(), deployer.address); + + await communityLocker.setTimeLimitPerMessage(newSchainName, 100); + + await erc721OnOriginChain.connect(deployer).mint(user.address, 3); + await erc721OnOriginChain.connect(user).approve(tokenManagerERC721.address, 3); + + await tokenManagerERC721 + .connect(user) + .transferToSchainERC721(newSchainName, erc721OnOriginChain.address, 3) + .should.be.eventually.rejectedWith("Exceeded message rate limit"); + + BigNumber.from(await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName)).should.be.deep.equal(BigNumber.from(2)); + + await skipTime(90); + + await tokenManagerERC721 + .connect(user) + .transferToSchainERC721(newSchainName, erc721OnOriginChain.address, 3) + .should.be.eventually.rejectedWith("Exceeded message rate limit"); + + BigNumber.from(await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName)).should.be.deep.equal(BigNumber.from(2)); + + await skipTime(20); + + await tokenManagerERC721 + .connect(user) + .transferToSchainERC721(newSchainName, erc721OnOriginChain.address, 3); + + BigNumber.from(await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName)).should.be.deep.equal(BigNumber.from(3)); + + await communityLocker.setTimeLimitPerMessage(newSchainName, 0); + + await erc721OnOriginChain.connect(deployer).mint(user.address, 4); + await erc721OnOriginChain.connect(user).approve(tokenManagerERC721.address, 4); + + await tokenManagerERC721 + .connect(user) + .transferToSchainERC721(newSchainName, erc721OnOriginChain.address, 4); + + BigNumber.from(await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName)).should.be.deep.equal(BigNumber.from(4)); + + await communityLocker.setTimeLimitPerMessage(newSchainName, 100); + + await erc721OnOriginChain.connect(deployer).mint(user.address, 5); + await erc721OnOriginChain.connect(user).approve(tokenManagerERC721.address, 5); + + await tokenManagerERC721 + .connect(user) + .transferToSchainERC721(newSchainName, erc721OnOriginChain.address, 5) + .should.be.eventually.rejectedWith("Exceeded message rate limit"); + + BigNumber.from(await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName)).should.be.deep.equal(BigNumber.from(4)); + + await skipTime(110); + + await tokenManagerERC721 + .connect(user) + .transferToSchainERC721(newSchainName, erc721OnOriginChain.address, 5); + + BigNumber.from(await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName)).should.be.deep.equal(BigNumber.from(5)); + }); + it("should invoke `transferToSchainERC721` and receive tokens without mistakes", async () => { await messageProxyForSchain.registerExtraContract(newSchainName, tokenManagerERC721.address); diff --git a/proxy/test/TokenManagerERC721WithMetadata.ts b/proxy/test/TokenManagerERC721WithMetadata.ts index 1aea17527..653f8cb94 100644 --- a/proxy/test/TokenManagerERC721WithMetadata.ts +++ b/proxy/test/TokenManagerERC721WithMetadata.ts @@ -35,6 +35,7 @@ import { } from "../typechain"; import { randomString, stringValue } from "./utils/helper"; +import { skipTime } from "./utils/time"; chai.should(); chai.use((chaiAsPromised as any)); @@ -121,7 +122,7 @@ describe("TokenManagerERC721WithMetadata", () => { await messageProxyForSchain.connect(deployer).grantRole(extraContractRegistrarRole, deployer.address); await communityLocker.grantRole(await communityLocker.CONSTANT_SETTER_ROLE(), deployer.address); - await communityLocker.setTimeLimitPerMessage(0); + await communityLocker.setTimeLimitPerMessage("Mainnet", 0); }); it("should change depositBox address", async () => { @@ -265,6 +266,106 @@ describe("TokenManagerERC721WithMetadata", () => { outgoingMessagesCounter.should.be.deep.equal(BigNumber.from(1)); }); + it("should reject `transferToSchainERC721` when executing earlier then allowed", async () => { + await messageProxyForSchain.registerExtraContract(newSchainName, tokenManagerERC721WithMetadata.address); + + // add connected chain: + await messageProxyForSchain.connect(deployer).grantRole(await messageProxyForSchain.CHAIN_CONNECTOR_ROLE(), deployer.address); + await messageProxyForSchain.connect(deployer).addConnectedChain(newSchainName); + + await erc721OnOriginChain.connect(deployer).mint(user.address, 1); + await erc721OnOriginChain.connect(user).approve(tokenManagerERC721WithMetadata.address, 1); + + await tokenManagerERC721WithMetadata + .connect(user) + .transferToSchainERC721(newSchainName, erc721OnOriginChain.address, 1) + .should.be.eventually.rejectedWith("Incorrect Token Manager address"); + + await tokenManagerERC721WithMetadata + .connect(user) + .transferToSchainERC721("Mainnet", erc721OnOriginChain.address, 1) + .should.be.eventually.rejectedWith("This function is not for transferring to Mainnet"); + + await tokenManagerERC721WithMetadata.addTokenManager(newSchainName, tokenManagerERC721WithMetadata2.address); + + await tokenManagerERC721WithMetadata + .connect(user) + .transferToSchainERC721(newSchainName, erc721OnOriginChain.address, 1); + + BigNumber.from(await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName)).should.be.deep.equal(BigNumber.from(1)); + + await erc721OnOriginChain.connect(deployer).mint(user.address, 2); + await erc721OnOriginChain.connect(user).approve(tokenManagerERC721WithMetadata.address, 2); + + await tokenManagerERC721WithMetadata + .connect(user) + .transferToSchainERC721(newSchainName, erc721OnOriginChain.address, 2); + + BigNumber.from(await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName)).should.be.deep.equal(BigNumber.from(2)); + + await communityLocker.grantRole(await communityLocker.CONSTANT_SETTER_ROLE(), deployer.address); + + await communityLocker.setTimeLimitPerMessage(newSchainName, 100); + + await erc721OnOriginChain.connect(deployer).mint(user.address, 3); + await erc721OnOriginChain.connect(user).approve(tokenManagerERC721WithMetadata.address, 3); + + await tokenManagerERC721WithMetadata + .connect(user) + .transferToSchainERC721(newSchainName, erc721OnOriginChain.address, 3) + .should.be.eventually.rejectedWith("Exceeded message rate limit"); + + BigNumber.from(await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName)).should.be.deep.equal(BigNumber.from(2)); + + await skipTime(90); + + await tokenManagerERC721WithMetadata + .connect(user) + .transferToSchainERC721(newSchainName, erc721OnOriginChain.address, 3) + .should.be.eventually.rejectedWith("Exceeded message rate limit"); + + BigNumber.from(await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName)).should.be.deep.equal(BigNumber.from(2)); + + await skipTime(20); + + await tokenManagerERC721WithMetadata + .connect(user) + .transferToSchainERC721(newSchainName, erc721OnOriginChain.address, 3); + + BigNumber.from(await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName)).should.be.deep.equal(BigNumber.from(3)); + + await communityLocker.setTimeLimitPerMessage(newSchainName, 0); + + await erc721OnOriginChain.connect(deployer).mint(user.address, 4); + await erc721OnOriginChain.connect(user).approve(tokenManagerERC721WithMetadata.address, 4); + + await tokenManagerERC721WithMetadata + .connect(user) + .transferToSchainERC721(newSchainName, erc721OnOriginChain.address, 4); + + BigNumber.from(await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName)).should.be.deep.equal(BigNumber.from(4)); + + await communityLocker.setTimeLimitPerMessage(newSchainName, 100); + + await erc721OnOriginChain.connect(deployer).mint(user.address, 5); + await erc721OnOriginChain.connect(user).approve(tokenManagerERC721WithMetadata.address, 5); + + await tokenManagerERC721WithMetadata + .connect(user) + .transferToSchainERC721(newSchainName, erc721OnOriginChain.address, 5) + .should.be.eventually.rejectedWith("Exceeded message rate limit"); + + BigNumber.from(await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName)).should.be.deep.equal(BigNumber.from(4)); + + await skipTime(110); + + await tokenManagerERC721WithMetadata + .connect(user) + .transferToSchainERC721(newSchainName, erc721OnOriginChain.address, 5); + + BigNumber.from(await messageProxyForSchain.getOutgoingMessagesCounter(newSchainName)).should.be.deep.equal(BigNumber.from(5)); + }); + it("should invoke `transferToSchainERC721` and receive tokens without mistakes", async () => { await messageProxyForSchain.registerExtraContract(newSchainName, tokenManagerERC721WithMetadata.address); diff --git a/proxy/test/TokenManagerEth.ts b/proxy/test/TokenManagerEth.ts index 635d73d0e..f77e79eb9 100644 --- a/proxy/test/TokenManagerEth.ts +++ b/proxy/test/TokenManagerEth.ts @@ -217,7 +217,7 @@ describe("TokenManagerEth", () => { await messageProxyForSchain.postMessage(communityLocker.address, mainnetHash, fakeCommunityPool, data1); await tokenManagerEth.connect(user).exitToMain(amountTo) - .should.be.eventually.rejectedWith("Trying to send messages too often"); + .should.be.eventually.rejectedWith("Exceeded message rate limit"); }); diff --git a/proxy/yarn.lock b/proxy/yarn.lock index 2dc6bc77f..6f2dff714 100644 --- a/proxy/yarn.lock +++ b/proxy/yarn.lock @@ -757,10 +757,10 @@ resolved "https://registry.yarnpkg.com/@skalenetwork/etherbase-interfaces/-/etherbase-interfaces-0.0.1-develop.20.tgz#33f61e18d695fd47063aa39dce4df335d26b9528" integrity sha512-j3xnuQtOtjvjAoUMJgSUFxRa9/Egkg1RyA8r6PjcEb33VksE4LWLBy0PNFUFehLZv48595JROTcViGeXXwg5HQ== -"@skalenetwork/ima-interfaces@1.0.0-develop.22": - version "1.0.0-develop.22" - resolved "https://registry.yarnpkg.com/@skalenetwork/ima-interfaces/-/ima-interfaces-1.0.0-develop.22.tgz#ffbdd626840669634b555782c33ef976c27a79a2" - integrity sha512-sdtfJJN0QIWnmESY56RV0L6EO0YsNaRp2OAXwCNe7WUnYz9J9xB6aoEsFww0nA+tlIQz8jYi5u23QhKi97E/xQ== +"@skalenetwork/ima-interfaces@1.0.0-develop.23": + version "1.0.0-develop.23" + resolved "https://registry.yarnpkg.com/@skalenetwork/ima-interfaces/-/ima-interfaces-1.0.0-develop.23.tgz#49f144e98ecac7f7daaa4e03d8a8a84269fe808c" + integrity sha512-Cd50gu0mtSuZgoxSUiwrFWgYbRdagJL0qM0nYX12t1HKY5OatMOGtc+Ok21NrIFEKQSDDFLpC2gF+pIklV8fXQ== dependencies: "@skalenetwork/skale-manager-interfaces" "^0.1.2" diff --git a/test/agent-test.js b/test/agent-test.js index da922465a..2ff55e927 100644 --- a/test/agent-test.js +++ b/test/agent-test.js @@ -117,6 +117,7 @@ global.imaState = { "strChainName_main_net": ( process.env.CHAIN_NAME_ETHEREUM || "Mainnet" ).toString().trim(), "strChainName_s_chain": ( process.env.CHAIN_NAME_SCHAIN || "Bob" ).toString().trim(), + "strChainName_origin_chain": ( process.env.CHAIN_NAME_ETHEREUM || "Mainnet" ).toString().trim(), "strChainName_t_chain": ( process.env.CHAIN_NAME_SCHAIN_TARGET || "Alice" ).toString().trim(), "cid_main_net": owaspUtils.toInteger( process.env.CID_ETHEREUM ) || -4, "cid_s_chain": owaspUtils.toInteger( process.env.CID_SCHAIN ) || -4, @@ -661,6 +662,7 @@ describe( "CLI", function() { "--url-s-chain=" + imaState.strURL_s_chain, "--id-main-net=" + imaState.strChainName_main_net, "--id-s-chain=" + imaState.strChainName_s_chain, + "--id-origin-chain=" + imaState.strChainName_origin_chain, "--cid-main-net=" + imaState.cid_main_net, "--cid-s-chain=" + imaState.cid_s_chain, "--address-main-net=" + imaState.joAccount_main_net.address(), diff --git a/test/tools/blockchain.py b/test/tools/blockchain.py index bb00268aa..16f7c2147 100644 --- a/test/tools/blockchain.py +++ b/test/tools/blockchain.py @@ -250,7 +250,7 @@ def recharge_user_wallet(self, from_key, schainName, amount_wei): def set_time_limit_per_message(self, from_key, time_limit): sender_address = self.key_to_address(from_key) community_locker = self._get_contract_on_schain('community_locker') - time_limit_abi = community_locker.encodeABI(fn_name="setTimeLimitPerMessage", args=[time_limit]) + time_limit_abi = community_locker.encodeABI(fn_name="setTimeLimitPerMessage", args=["Mainnet", time_limit]) signed_txn = self.web3_schain.eth.account.signTransaction(dict( nonce=self.web3_schain.eth.getTransactionCount(sender_address), gasPrice=self.web3_schain.eth.gasPrice,