diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 4af1da36f..d1c9b8bdd 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -8,11 +8,13 @@ on: - develop - beta - stable + push: + tags: + - 'custom-release-*' jobs: build: runs-on: ubuntu-latest - if: github.event.pull_request.merged env: DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }} @@ -49,7 +51,6 @@ jobs: with: python-version: 3.8 - - name: Build and publish container run: | export BRANCH=${GITHUB_REF##*/} @@ -92,21 +93,21 @@ jobs: working-directory: ${{env.PROXY_DIR}} env: VERSION: ${{ env.VERSION }} - run: | + run: | ./predeployed/scripts/build_package.sh - name: Publish predeployed pip package working-directory: ${{env.PROXY_DIR}} env: PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }} - run: | + run: | ./predeployed/scripts/publish_package.sh - name: Generate ABIs working-directory: ${{env.PROXY_DIR}}/predeployed env: VERSION: ${{ env.VERSION }} - run: | + run: | python3 -m venv scripts/venv source scripts/venv/bin/activate pip install dist/ima_predeployed-*.whl @@ -123,7 +124,7 @@ jobs: release_name: ${{ env.VERSION }} draft: false prerelease: ${{ env.PRERELEASE }} - + - name: Upload Release Assets id: upload-release-assets uses: dwenegar/upload-release-assets@v1 diff --git a/VERSION b/VERSION index dc1e644a1..227cea215 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.6.0 +2.0.0 diff --git a/npms/skale-observer/observer.mjs b/npms/skale-observer/observer.mjs index a914f82ab..243024da0 100644 --- a/npms/skale-observer/observer.mjs +++ b/npms/skale-observer/observer.mjs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: AGPL-3.0-only /** diff --git a/npms/skale-observer/observerWorker.mjs b/npms/skale-observer/observerWorker.mjs index 520814c4d..8e13d6235 100644 --- a/npms/skale-observer/observerWorker.mjs +++ b/npms/skale-observer/observerWorker.mjs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: AGPL-3.0-only /** diff --git a/npms/skale-owasp/owaspUtils.mjs b/npms/skale-owasp/owaspUtils.mjs index 8ceb80536..7531f04ca 100644 --- a/npms/skale-owasp/owaspUtils.mjs +++ b/npms/skale-owasp/owaspUtils.mjs @@ -1,4 +1,3 @@ - // SPDX-License-Identifier: AGPL-3.0-only /** diff --git a/proxy/.openzeppelin/mainnet.json b/proxy/.openzeppelin/mainnet.json index 964bddbc9..36ebdc5cf 100644 --- a/proxy/.openzeppelin/mainnet.json +++ b/proxy/.openzeppelin/mainnet.json @@ -5903,7 +5903,7 @@ { "contract": "Initializable", "label": "_initialized", - "type": "t_bool", + "type": "t_uint8", "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:21" }, { @@ -6121,7 +6121,7 @@ { "contract": "Initializable", "label": "_initialized", - "type": "t_bool", + "type": "t_uint8", "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:21" }, { @@ -6307,7 +6307,7 @@ { "contract": "Initializable", "label": "_initialized", - "type": "t_bool", + "type": "t_uint8", "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:21" }, { @@ -6487,7 +6487,7 @@ { "contract": "Initializable", "label": "_initialized", - "type": "t_bool", + "type": "t_uint8", "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:21" }, { @@ -6679,7 +6679,7 @@ { "contract": "Initializable", "label": "_initialized", - "type": "t_bool", + "type": "t_uint8", "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:21" }, { @@ -6877,7 +6877,7 @@ { "contract": "Initializable", "label": "_initialized", - "type": "t_bool", + "type": "t_uint8", "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:21" }, { @@ -7075,7 +7075,7 @@ { "contract": "Initializable", "label": "_initialized", - "type": "t_bool", + "type": "t_uint8", "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:21" }, { @@ -7273,6 +7273,2873 @@ } } } + }, + "3622da58837ec6a715bb7177e0e4abd52b6f06ccae45304744665adce6974a38": { + "address": "0xC261084Dc6475d4980548Bd8C323FF825b3D0C38", + "txHash": "0xedeaefffa86911da5334b4c8a231fa8f70c6be9007de26306eae9b4ed1d8ad78", + "layout": { + "storage": [ + { + "contract": "Initializable", + "label": "_initialized", + "type": "t_uint8", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:62" + }, + { + "contract": "Initializable", + "label": "_initializing", + "type": "t_bool", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:67" + }, + { + "contract": "ContextUpgradeable", + "label": "__gap", + "type": "t_array(t_uint256)50_storage", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" + }, + { + "contract": "ERC165Upgradeable", + "label": "__gap", + "type": "t_array(t_uint256)50_storage", + "src": "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol:41" + }, + { + "contract": "AccessControlUpgradeable", + "label": "_roles", + "type": "t_mapping(t_bytes32,t_struct(RoleData)179_storage)", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:61" + }, + { + "contract": "AccessControlUpgradeable", + "label": "__gap", + "type": "t_array(t_uint256)49_storage", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:259" + }, + { + "contract": "AccessControlEnumerableUpgradeable", + "label": "_roleMembers", + "type": "t_mapping(t_bytes32,t_struct(AddressSet)8661_storage)", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol:22" + }, + { + "contract": "AccessControlEnumerableUpgradeable", + "label": "__gap", + "type": "t_array(t_uint256)49_storage", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol:76" + }, + { + "contract": "SkaleManagerClient", + "label": "contractManagerOfSkaleManager", + "type": "t_contract(IContractManager)10439", + "src": "contracts/mainnet/SkaleManagerClient.sol:37" + }, + { + "contract": "MessageProxy", + "label": "connectedChains", + "type": "t_mapping(t_bytes32,t_struct(ConnectedChainInfo)11136_storage)", + "src": "contracts/MessageProxy.sol:58" + }, + { + "contract": "MessageProxy", + "label": "deprecatedRegistryContracts", + "type": "t_mapping(t_bytes32,t_mapping(t_address,t_bool))", + "src": "contracts/MessageProxy.sol:61" + }, + { + "contract": "MessageProxy", + "label": "gasLimit", + "type": "t_uint256", + "src": "contracts/MessageProxy.sol:63" + }, + { + "contract": "MessageProxyForMainnet", + "label": "communityPool", + "type": "t_contract(ICommunityPool)9708", + "src": "contracts/mainnet/MessageProxyForMainnet.sol:72" + }, + { + "contract": "MessageProxyForMainnet", + "label": "headerMessageGasCost", + "type": "t_uint256", + "src": "contracts/mainnet/MessageProxyForMainnet.sol:74" + }, + { + "contract": "MessageProxyForMainnet", + "label": "messageGasCost", + "type": "t_uint256", + "src": "contracts/mainnet/MessageProxyForMainnet.sol:75" + }, + { + "contract": "MessageProxyForMainnet", + "label": "_registryContracts", + "type": "t_mapping(t_bytes32,t_struct(AddressSet)8661_storage)", + "src": "contracts/mainnet/MessageProxyForMainnet.sol:80" + }, + { + "contract": "MessageProxyForMainnet", + "label": "version", + "type": "t_string_storage", + "src": "contracts/mainnet/MessageProxyForMainnet.sol:81" + }, + { + "contract": "MessageProxyForMainnet", + "label": "messageInProgress", + "type": "t_bool", + "src": "contracts/mainnet/MessageProxyForMainnet.sol:82" + }, + { + "contract": "MessageProxyForMainnet", + "label": "pauseInfo", + "type": "t_mapping(t_bytes32,t_struct(Pause)19540_storage)", + "src": "contracts/mainnet/MessageProxyForMainnet.sol:85" + } + ], + "types": { + "t_contract(ICommunityPool)9708": { + "label": "contract ICommunityPool" + }, + "t_uint256": { + "label": "uint256" + }, + "t_mapping(t_bytes32,t_struct(AddressSet)8661_storage)": { + "label": "mapping(bytes32 => struct EnumerableSetUpgradeable.AddressSet)" + }, + "t_bytes32": { + "label": "bytes32" + }, + "t_struct(AddressSet)8661_storage": { + "label": "struct EnumerableSetUpgradeable.AddressSet", + "members": [ + { + "label": "_inner", + "type": "t_struct(Set)8360_storage" + } + ] + }, + "t_struct(Set)8360_storage": { + "label": "struct EnumerableSetUpgradeable.Set", + "members": [ + { + "label": "_values", + "type": "t_array(t_bytes32)dyn_storage" + }, + { + "label": "_indexes", + "type": "t_mapping(t_bytes32,t_uint256)" + } + ] + }, + "t_array(t_bytes32)dyn_storage": { + "label": "bytes32[]" + }, + "t_mapping(t_bytes32,t_uint256)": { + "label": "mapping(bytes32 => uint256)" + }, + "t_string_storage": { + "label": "string" + }, + "t_bool": { + "label": "bool" + }, + "t_mapping(t_bytes32,t_struct(Pause)19540_storage)": { + "label": "mapping(bytes32 => struct MessageProxyForMainnet.Pause)" + }, + "t_struct(Pause)19540_storage": { + "label": "struct MessageProxyForMainnet.Pause", + "members": [ + { + "label": "paused", + "type": "t_bool" + } + ] + }, + "t_mapping(t_bytes32,t_struct(ConnectedChainInfo)11136_storage)": { + "label": "mapping(bytes32 => struct MessageProxy.ConnectedChainInfo)" + }, + "t_struct(ConnectedChainInfo)11136_storage": { + "label": "struct MessageProxy.ConnectedChainInfo", + "members": [ + { + "label": "incomingMessageCounter", + "type": "t_uint256" + }, + { + "label": "outgoingMessageCounter", + "type": "t_uint256" + }, + { + "label": "inited", + "type": "t_bool" + } + ] + }, + "t_mapping(t_bytes32,t_mapping(t_address,t_bool))": { + "label": "mapping(bytes32 => mapping(address => bool))" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)" + }, + "t_address": { + "label": "address" + }, + "t_contract(IContractManager)10439": { + "label": "contract IContractManager" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]" + }, + "t_mapping(t_bytes32,t_struct(RoleData)179_storage)": { + "label": "mapping(bytes32 => struct AccessControlUpgradeable.RoleData)" + }, + "t_struct(RoleData)179_storage": { + "label": "struct AccessControlUpgradeable.RoleData", + "members": [ + { + "label": "members", + "type": "t_mapping(t_address,t_bool)" + }, + { + "label": "adminRole", + "type": "t_bytes32" + } + ] + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]" + }, + "t_uint8": { + "label": "uint8" + } + } + } + }, + "be5f43ef1b09eacc8934bd9644f84fd79173f4ea3ed4c8c212649f0c2576eeca": { + "address": "0xEde996A9899b570dE70eaDE06Fa69621cE1470Be", + "txHash": "0x02b7cf351a60df17afb174d1912991f9f36d34ab5f22d4c819d84b386a0c78fe", + "layout": { + "storage": [ + { + "contract": "Initializable", + "label": "_initialized", + "type": "t_uint8", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:62" + }, + { + "contract": "Initializable", + "label": "_initializing", + "type": "t_bool", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:67" + }, + { + "contract": "ContextUpgradeable", + "label": "__gap", + "type": "t_array(t_uint256)50_storage", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" + }, + { + "contract": "ERC165Upgradeable", + "label": "__gap", + "type": "t_array(t_uint256)50_storage", + "src": "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol:41" + }, + { + "contract": "AccessControlUpgradeable", + "label": "_roles", + "type": "t_mapping(t_bytes32,t_struct(RoleData)179_storage)", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:61" + }, + { + "contract": "AccessControlUpgradeable", + "label": "__gap", + "type": "t_array(t_uint256)49_storage", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:259" + }, + { + "contract": "AccessControlEnumerableUpgradeable", + "label": "_roleMembers", + "type": "t_mapping(t_bytes32,t_struct(AddressSet)8661_storage)", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol:22" + }, + { + "contract": "AccessControlEnumerableUpgradeable", + "label": "__gap", + "type": "t_array(t_uint256)49_storage", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol:76" + }, + { + "contract": "SkaleManagerClient", + "label": "contractManagerOfSkaleManager", + "type": "t_contract(IContractManager)10439", + "src": "contracts/mainnet/SkaleManagerClient.sol:37" + }, + { + "contract": "Twin", + "label": "messageProxy", + "type": "t_contract(IMessageProxyForMainnet)9852", + "src": "contracts/mainnet/Twin.sol:38" + }, + { + "contract": "Twin", + "label": "schainLinks", + "type": "t_mapping(t_bytes32,t_address)", + "src": "contracts/mainnet/Twin.sol:39" + }, + { + "contract": "Linker", + "label": "_mainnetContracts", + "type": "t_struct(AddressSet)8661_storage", + "src": "contracts/mainnet/Linker.sol:44" + }, + { + "contract": "Linker", + "label": "_interchainConnections", + "type": "t_mapping(t_bytes32,t_bool)", + "src": "contracts/mainnet/Linker.sol:47" + }, + { + "contract": "Linker", + "label": "statuses", + "type": "t_mapping(t_bytes32,t_enum(KillProcess)19125)", + "src": "contracts/mainnet/Linker.sol:51" + } + ], + "types": { + "t_struct(AddressSet)8661_storage": { + "label": "struct EnumerableSetUpgradeable.AddressSet", + "members": [ + { + "label": "_inner", + "type": "t_struct(Set)8360_storage" + } + ] + }, + "t_struct(Set)8360_storage": { + "label": "struct EnumerableSetUpgradeable.Set", + "members": [ + { + "label": "_values", + "type": "t_array(t_bytes32)dyn_storage" + }, + { + "label": "_indexes", + "type": "t_mapping(t_bytes32,t_uint256)" + } + ] + }, + "t_array(t_bytes32)dyn_storage": { + "label": "bytes32[]" + }, + "t_bytes32": { + "label": "bytes32" + }, + "t_mapping(t_bytes32,t_uint256)": { + "label": "mapping(bytes32 => uint256)" + }, + "t_uint256": { + "label": "uint256" + }, + "t_mapping(t_bytes32,t_bool)": { + "label": "mapping(bytes32 => bool)" + }, + "t_bool": { + "label": "bool" + }, + "t_mapping(t_bytes32,t_enum(KillProcess)19125)": { + "label": "mapping(bytes32 => enum Linker.KillProcess)" + }, + "t_enum(KillProcess)19125": { + "label": "enum Linker.KillProcess", + "members": [ + "NotKilled", + "PartiallyKilledBySchainOwner", + "PartiallyKilledByContractOwner", + "Killed" + ] + }, + "t_contract(IMessageProxyForMainnet)9852": { + "label": "contract IMessageProxyForMainnet" + }, + "t_mapping(t_bytes32,t_address)": { + "label": "mapping(bytes32 => address)" + }, + "t_address": { + "label": "address" + }, + "t_contract(IContractManager)10439": { + "label": "contract IContractManager" + }, + "t_mapping(t_bytes32,t_struct(AddressSet)8661_storage)": { + "label": "mapping(bytes32 => struct EnumerableSetUpgradeable.AddressSet)" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]" + }, + "t_mapping(t_bytes32,t_struct(RoleData)179_storage)": { + "label": "mapping(bytes32 => struct AccessControlUpgradeable.RoleData)" + }, + "t_struct(RoleData)179_storage": { + "label": "struct AccessControlUpgradeable.RoleData", + "members": [ + { + "label": "members", + "type": "t_mapping(t_address,t_bool)" + }, + { + "label": "adminRole", + "type": "t_bytes32" + } + ] + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]" + }, + "t_uint8": { + "label": "uint8" + } + } + } + }, + "5e36dd460ee62e62cfe850c673b47ca31f1a405d93f219217e0f4a627a8048a2": { + "address": "0xAC1861ed87595E0AfF6C2bB9f8742D3308f48ba0", + "txHash": "0xc9155c27d61c3aa21cf792b0e22ce4b30792391ff7460f363697fa344b6bd6bf", + "layout": { + "storage": [ + { + "contract": "Initializable", + "label": "_initialized", + "type": "t_uint8", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:62" + }, + { + "contract": "Initializable", + "label": "_initializing", + "type": "t_bool", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:67" + }, + { + "contract": "ContextUpgradeable", + "label": "__gap", + "type": "t_array(t_uint256)50_storage", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" + }, + { + "contract": "ERC165Upgradeable", + "label": "__gap", + "type": "t_array(t_uint256)50_storage", + "src": "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol:41" + }, + { + "contract": "AccessControlUpgradeable", + "label": "_roles", + "type": "t_mapping(t_bytes32,t_struct(RoleData)179_storage)", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:61" + }, + { + "contract": "AccessControlUpgradeable", + "label": "__gap", + "type": "t_array(t_uint256)49_storage", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:259" + }, + { + "contract": "AccessControlEnumerableUpgradeable", + "label": "_roleMembers", + "type": "t_mapping(t_bytes32,t_struct(AddressSet)8661_storage)", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol:22" + }, + { + "contract": "AccessControlEnumerableUpgradeable", + "label": "__gap", + "type": "t_array(t_uint256)49_storage", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol:76" + }, + { + "contract": "SkaleManagerClient", + "label": "contractManagerOfSkaleManager", + "type": "t_contract(IContractManager)10439", + "src": "contracts/mainnet/SkaleManagerClient.sol:37" + }, + { + "contract": "Twin", + "label": "messageProxy", + "type": "t_contract(IMessageProxyForMainnet)9852", + "src": "contracts/mainnet/Twin.sol:38" + }, + { + "contract": "Twin", + "label": "schainLinks", + "type": "t_mapping(t_bytes32,t_address)", + "src": "contracts/mainnet/Twin.sol:39" + }, + { + "contract": "CommunityPool", + "label": "_userWallets", + "type": "t_mapping(t_address,t_mapping(t_bytes32,t_uint256))", + "src": "contracts/mainnet/CommunityPool.sol:44" + }, + { + "contract": "CommunityPool", + "label": "activeUsers", + "type": "t_mapping(t_address,t_mapping(t_bytes32,t_bool))", + "src": "contracts/mainnet/CommunityPool.sol:47" + }, + { + "contract": "CommunityPool", + "label": "minTransactionGas", + "type": "t_uint256", + "src": "contracts/mainnet/CommunityPool.sol:49" + }, + { + "contract": "CommunityPool", + "label": "multiplierNumerator", + "type": "t_uint256", + "src": "contracts/mainnet/CommunityPool.sol:51" + }, + { + "contract": "CommunityPool", + "label": "multiplierDivider", + "type": "t_uint256", + "src": "contracts/mainnet/CommunityPool.sol:52" + } + ], + "types": { + "t_mapping(t_address,t_mapping(t_bytes32,t_uint256))": { + "label": "mapping(address => mapping(bytes32 => uint256))" + }, + "t_address": { + "label": "address" + }, + "t_mapping(t_bytes32,t_uint256)": { + "label": "mapping(bytes32 => uint256)" + }, + "t_bytes32": { + "label": "bytes32" + }, + "t_uint256": { + "label": "uint256" + }, + "t_mapping(t_address,t_mapping(t_bytes32,t_bool))": { + "label": "mapping(address => mapping(bytes32 => bool))" + }, + "t_mapping(t_bytes32,t_bool)": { + "label": "mapping(bytes32 => bool)" + }, + "t_bool": { + "label": "bool" + }, + "t_contract(IMessageProxyForMainnet)9852": { + "label": "contract IMessageProxyForMainnet" + }, + "t_mapping(t_bytes32,t_address)": { + "label": "mapping(bytes32 => address)" + }, + "t_contract(IContractManager)10439": { + "label": "contract IContractManager" + }, + "t_mapping(t_bytes32,t_struct(AddressSet)8661_storage)": { + "label": "mapping(bytes32 => struct EnumerableSetUpgradeable.AddressSet)" + }, + "t_struct(AddressSet)8661_storage": { + "label": "struct EnumerableSetUpgradeable.AddressSet", + "members": [ + { + "label": "_inner", + "type": "t_struct(Set)8360_storage" + } + ] + }, + "t_struct(Set)8360_storage": { + "label": "struct EnumerableSetUpgradeable.Set", + "members": [ + { + "label": "_values", + "type": "t_array(t_bytes32)dyn_storage" + }, + { + "label": "_indexes", + "type": "t_mapping(t_bytes32,t_uint256)" + } + ] + }, + "t_array(t_bytes32)dyn_storage": { + "label": "bytes32[]" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]" + }, + "t_mapping(t_bytes32,t_struct(RoleData)179_storage)": { + "label": "mapping(bytes32 => struct AccessControlUpgradeable.RoleData)" + }, + "t_struct(RoleData)179_storage": { + "label": "struct AccessControlUpgradeable.RoleData", + "members": [ + { + "label": "members", + "type": "t_mapping(t_address,t_bool)" + }, + { + "label": "adminRole", + "type": "t_bytes32" + } + ] + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]" + }, + "t_uint8": { + "label": "uint8" + } + } + } + }, + "39a9414e6c3405f4b73d2c4bde389d583146d93c02e5ed4461d0da6d4980863c": { + "address": "0x998D6AA8CaC99f1557b65E680fc4FDCD94Be70ca", + "txHash": "0xc666170c9ada0cec01b9fa0d440ee5a83a9bf62ddde5b56c37bdbaa7d914adc1", + "layout": { + "storage": [ + { + "contract": "Initializable", + "label": "_initialized", + "type": "t_uint8", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:62" + }, + { + "contract": "Initializable", + "label": "_initializing", + "type": "t_bool", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:67" + }, + { + "contract": "ContextUpgradeable", + "label": "__gap", + "type": "t_array(t_uint256)50_storage", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" + }, + { + "contract": "ERC165Upgradeable", + "label": "__gap", + "type": "t_array(t_uint256)50_storage", + "src": "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol:41" + }, + { + "contract": "AccessControlUpgradeable", + "label": "_roles", + "type": "t_mapping(t_bytes32,t_struct(RoleData)179_storage)", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:61" + }, + { + "contract": "AccessControlUpgradeable", + "label": "__gap", + "type": "t_array(t_uint256)49_storage", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:259" + }, + { + "contract": "AccessControlEnumerableUpgradeable", + "label": "_roleMembers", + "type": "t_mapping(t_bytes32,t_struct(AddressSet)8661_storage)", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol:22" + }, + { + "contract": "AccessControlEnumerableUpgradeable", + "label": "__gap", + "type": "t_array(t_uint256)49_storage", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol:76" + }, + { + "contract": "SkaleManagerClient", + "label": "contractManagerOfSkaleManager", + "type": "t_contract(IContractManager)10382", + "src": "contracts/mainnet/SkaleManagerClient.sol:37" + }, + { + "contract": "Twin", + "label": "messageProxy", + "type": "t_contract(IMessageProxyForMainnet)9795", + "src": "contracts/mainnet/Twin.sol:38" + }, + { + "contract": "Twin", + "label": "schainLinks", + "type": "t_mapping(t_bytes32,t_address)", + "src": "contracts/mainnet/Twin.sol:39" + }, + { + "contract": "DepositBox", + "label": "linker", + "type": "t_contract(ILinker)9750", + "src": "contracts/mainnet/DepositBox.sol:36" + }, + { + "contract": "DepositBox", + "label": "_automaticDeploy", + "type": "t_mapping(t_bytes32,t_bool)", + "src": "contracts/mainnet/DepositBox.sol:39" + }, + { + "contract": "DepositBoxEth", + "label": "approveTransfers", + "type": "t_mapping(t_address,t_uint256)", + "src": "contracts/mainnet/DepositBoxes/DepositBoxEth.sol:39" + }, + { + "contract": "DepositBoxEth", + "label": "transferredAmount", + "type": "t_mapping(t_bytes32,t_uint256)", + "src": "contracts/mainnet/DepositBoxes/DepositBoxEth.sol:41" + }, + { + "contract": "DepositBoxEth", + "label": "activeEthTransfers", + "type": "t_mapping(t_bytes32,t_bool)", + "src": "contracts/mainnet/DepositBoxes/DepositBoxEth.sol:43" + } + ], + "types": { + "t_mapping(t_address,t_uint256)": { + "label": "mapping(address => uint256)" + }, + "t_address": { + "label": "address" + }, + "t_uint256": { + "label": "uint256" + }, + "t_mapping(t_bytes32,t_uint256)": { + "label": "mapping(bytes32 => uint256)" + }, + "t_bytes32": { + "label": "bytes32" + }, + "t_mapping(t_bytes32,t_bool)": { + "label": "mapping(bytes32 => bool)" + }, + "t_bool": { + "label": "bool" + }, + "t_contract(ILinker)9750": { + "label": "contract ILinker" + }, + "t_contract(IMessageProxyForMainnet)9795": { + "label": "contract IMessageProxyForMainnet" + }, + "t_mapping(t_bytes32,t_address)": { + "label": "mapping(bytes32 => address)" + }, + "t_contract(IContractManager)10382": { + "label": "contract IContractManager" + }, + "t_mapping(t_bytes32,t_struct(AddressSet)8661_storage)": { + "label": "mapping(bytes32 => struct EnumerableSetUpgradeable.AddressSet)" + }, + "t_struct(AddressSet)8661_storage": { + "label": "struct EnumerableSetUpgradeable.AddressSet", + "members": [ + { + "label": "_inner", + "type": "t_struct(Set)8360_storage" + } + ] + }, + "t_struct(Set)8360_storage": { + "label": "struct EnumerableSetUpgradeable.Set", + "members": [ + { + "label": "_values", + "type": "t_array(t_bytes32)dyn_storage" + }, + { + "label": "_indexes", + "type": "t_mapping(t_bytes32,t_uint256)" + } + ] + }, + "t_array(t_bytes32)dyn_storage": { + "label": "bytes32[]" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]" + }, + "t_mapping(t_bytes32,t_struct(RoleData)179_storage)": { + "label": "mapping(bytes32 => struct AccessControlUpgradeable.RoleData)" + }, + "t_struct(RoleData)179_storage": { + "label": "struct AccessControlUpgradeable.RoleData", + "members": [ + { + "label": "members", + "type": "t_mapping(t_address,t_bool)" + }, + { + "label": "adminRole", + "type": "t_bytes32" + } + ] + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]" + }, + "t_uint8": { + "label": "uint8" + } + } + } + }, + "10b740355b58700c23bb43bffc6103dff368b689c2d205faac2fc9fe0aaea2de": { + "address": "0x4B4192649E9450f329dD36F56a81C08aD0c12c02", + "txHash": "0xa3d60753d4655bb28a64b70674335588fe0db268b9cd22b33c35e578c01a2d92", + "layout": { + "storage": [ + { + "contract": "Initializable", + "label": "_initialized", + "type": "t_uint8", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:62" + }, + { + "contract": "Initializable", + "label": "_initializing", + "type": "t_bool", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:67" + }, + { + "contract": "ContextUpgradeable", + "label": "__gap", + "type": "t_array(t_uint256)50_storage", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" + }, + { + "contract": "ERC165Upgradeable", + "label": "__gap", + "type": "t_array(t_uint256)50_storage", + "src": "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol:41" + }, + { + "contract": "AccessControlUpgradeable", + "label": "_roles", + "type": "t_mapping(t_bytes32,t_struct(RoleData)179_storage)", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:61" + }, + { + "contract": "AccessControlUpgradeable", + "label": "__gap", + "type": "t_array(t_uint256)49_storage", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:259" + }, + { + "contract": "AccessControlEnumerableUpgradeable", + "label": "_roleMembers", + "type": "t_mapping(t_bytes32,t_struct(AddressSet)8661_storage)", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol:22" + }, + { + "contract": "AccessControlEnumerableUpgradeable", + "label": "__gap", + "type": "t_array(t_uint256)49_storage", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol:76" + }, + { + "contract": "SkaleManagerClient", + "label": "contractManagerOfSkaleManager", + "type": "t_contract(IContractManager)10382", + "src": "contracts/mainnet/SkaleManagerClient.sol:37" + }, + { + "contract": "Twin", + "label": "messageProxy", + "type": "t_contract(IMessageProxyForMainnet)9795", + "src": "contracts/mainnet/Twin.sol:38" + }, + { + "contract": "Twin", + "label": "schainLinks", + "type": "t_mapping(t_bytes32,t_address)", + "src": "contracts/mainnet/Twin.sol:39" + }, + { + "contract": "DepositBox", + "label": "linker", + "type": "t_contract(ILinker)9750", + "src": "contracts/mainnet/DepositBox.sol:36" + }, + { + "contract": "DepositBox", + "label": "_automaticDeploy", + "type": "t_mapping(t_bytes32,t_bool)", + "src": "contracts/mainnet/DepositBox.sol:39" + }, + { + "contract": "DepositBoxERC20", + "label": "_deprecatedSchainToERC20", + "type": "t_mapping(t_bytes32,t_mapping(t_address,t_bool))", + "src": "contracts/mainnet/DepositBoxes/DepositBoxERC20.sol:84" + }, + { + "contract": "DepositBoxERC20", + "label": "transferredAmount", + "type": "t_mapping(t_bytes32,t_mapping(t_address,t_uint256))", + "src": "contracts/mainnet/DepositBoxes/DepositBoxERC20.sol:85" + }, + { + "contract": "DepositBoxERC20", + "label": "_schainToERC20", + "type": "t_mapping(t_bytes32,t_struct(AddressSet)8661_storage)", + "src": "contracts/mainnet/DepositBoxes/DepositBoxERC20.sol:86" + }, + { + "contract": "DepositBoxERC20", + "label": "_delayConfig", + "type": "t_mapping(t_bytes32,t_struct(DelayConfig)15776_storage)", + "src": "contracts/mainnet/DepositBoxes/DepositBoxERC20.sol:90" + }, + { + "contract": "DepositBoxERC20", + "label": "delayedTransfersSize", + "type": "t_uint256", + "src": "contracts/mainnet/DepositBoxes/DepositBoxERC20.sol:92" + }, + { + "contract": "DepositBoxERC20", + "label": "delayedTransfers", + "type": "t_mapping(t_uint256,t_struct(DelayedTransfer)15764_storage)", + "src": "contracts/mainnet/DepositBoxes/DepositBoxERC20.sol:94" + }, + { + "contract": "DepositBoxERC20", + "label": "delayedTransfersByReceiver", + "type": "t_mapping(t_address,t_struct(Bytes32Deque)8027_storage)", + "src": "contracts/mainnet/DepositBoxes/DepositBoxERC20.sol:96" + } + ], + "types": { + "t_mapping(t_bytes32,t_mapping(t_address,t_bool))": { + "label": "mapping(bytes32 => mapping(address => bool))" + }, + "t_bytes32": { + "label": "bytes32" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)" + }, + "t_address": { + "label": "address" + }, + "t_bool": { + "label": "bool" + }, + "t_mapping(t_bytes32,t_mapping(t_address,t_uint256))": { + "label": "mapping(bytes32 => mapping(address => uint256))" + }, + "t_mapping(t_address,t_uint256)": { + "label": "mapping(address => uint256)" + }, + "t_uint256": { + "label": "uint256" + }, + "t_mapping(t_bytes32,t_struct(AddressSet)8661_storage)": { + "label": "mapping(bytes32 => struct EnumerableSetUpgradeable.AddressSet)" + }, + "t_struct(AddressSet)8661_storage": { + "label": "struct EnumerableSetUpgradeable.AddressSet", + "members": [ + { + "label": "_inner", + "type": "t_struct(Set)8360_storage" + } + ] + }, + "t_struct(Set)8360_storage": { + "label": "struct EnumerableSetUpgradeable.Set", + "members": [ + { + "label": "_values", + "type": "t_array(t_bytes32)dyn_storage" + }, + { + "label": "_indexes", + "type": "t_mapping(t_bytes32,t_uint256)" + } + ] + }, + "t_array(t_bytes32)dyn_storage": { + "label": "bytes32[]" + }, + "t_mapping(t_bytes32,t_uint256)": { + "label": "mapping(bytes32 => uint256)" + }, + "t_mapping(t_bytes32,t_struct(DelayConfig)15776_storage)": { + "label": "mapping(bytes32 => struct DepositBoxERC20.DelayConfig)" + }, + "t_struct(DelayConfig)15776_storage": { + "label": "struct DepositBoxERC20.DelayConfig", + "members": [ + { + "label": "bigTransferThreshold", + "type": "t_mapping(t_address,t_uint256)" + }, + { + "label": "trustedReceivers", + "type": "t_struct(AddressSet)8661_storage" + }, + { + "label": "transferDelay", + "type": "t_uint256" + }, + { + "label": "arbitrageDuration", + "type": "t_uint256" + } + ] + }, + "t_mapping(t_uint256,t_struct(DelayedTransfer)15764_storage)": { + "label": "mapping(uint256 => struct DepositBoxERC20.DelayedTransfer)" + }, + "t_struct(DelayedTransfer)15764_storage": { + "label": "struct DepositBoxERC20.DelayedTransfer", + "members": [ + { + "label": "receiver", + "type": "t_address" + }, + { + "label": "schainHash", + "type": "t_bytes32" + }, + { + "label": "token", + "type": "t_address" + }, + { + "label": "amount", + "type": "t_uint256" + }, + { + "label": "untilTimestamp", + "type": "t_uint256" + }, + { + "label": "status", + "type": "t_enum(DelayedTransferStatus)15750" + } + ] + }, + "t_enum(DelayedTransferStatus)15750": { + "label": "enum DepositBoxERC20.DelayedTransferStatus", + "members": [ + "DELAYED", + "ARBITRAGE", + "COMPLETED" + ] + }, + "t_mapping(t_address,t_struct(Bytes32Deque)8027_storage)": { + "label": "mapping(address => struct DoubleEndedQueueUpgradeable.Bytes32Deque)" + }, + "t_struct(Bytes32Deque)8027_storage": { + "label": "struct DoubleEndedQueueUpgradeable.Bytes32Deque", + "members": [ + { + "label": "_begin", + "type": "t_int128" + }, + { + "label": "_end", + "type": "t_int128" + }, + { + "label": "_data", + "type": "t_mapping(t_int128,t_bytes32)" + } + ] + }, + "t_int128": { + "label": "int128" + }, + "t_mapping(t_int128,t_bytes32)": { + "label": "mapping(int128 => bytes32)" + }, + "t_contract(ILinker)9750": { + "label": "contract ILinker" + }, + "t_mapping(t_bytes32,t_bool)": { + "label": "mapping(bytes32 => bool)" + }, + "t_contract(IMessageProxyForMainnet)9795": { + "label": "contract IMessageProxyForMainnet" + }, + "t_mapping(t_bytes32,t_address)": { + "label": "mapping(bytes32 => address)" + }, + "t_contract(IContractManager)10382": { + "label": "contract IContractManager" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]" + }, + "t_mapping(t_bytes32,t_struct(RoleData)179_storage)": { + "label": "mapping(bytes32 => struct AccessControlUpgradeable.RoleData)" + }, + "t_struct(RoleData)179_storage": { + "label": "struct AccessControlUpgradeable.RoleData", + "members": [ + { + "label": "members", + "type": "t_mapping(t_address,t_bool)" + }, + { + "label": "adminRole", + "type": "t_bytes32" + } + ] + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]" + }, + "t_uint8": { + "label": "uint8" + } + } + } + }, + "74a3adbddb234aaf28561dae38c6e0cad571c7b9f8c2b7853db06ab9b9ec35c0": { + "address": "0x205fDFa8BB5b035152d9aca24cA32377A98838b8", + "txHash": "0x1897f89e94608ea48e711ef88a7daa0ba38ae3c01a6205e14ecf92c26bd70288", + "layout": { + "storage": [ + { + "contract": "Initializable", + "label": "_initialized", + "type": "t_uint8", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:62" + }, + { + "contract": "Initializable", + "label": "_initializing", + "type": "t_bool", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:67" + }, + { + "contract": "ContextUpgradeable", + "label": "__gap", + "type": "t_array(t_uint256)50_storage", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" + }, + { + "contract": "ERC165Upgradeable", + "label": "__gap", + "type": "t_array(t_uint256)50_storage", + "src": "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol:41" + }, + { + "contract": "AccessControlUpgradeable", + "label": "_roles", + "type": "t_mapping(t_bytes32,t_struct(RoleData)179_storage)", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:61" + }, + { + "contract": "AccessControlUpgradeable", + "label": "__gap", + "type": "t_array(t_uint256)49_storage", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:259" + }, + { + "contract": "AccessControlEnumerableUpgradeable", + "label": "_roleMembers", + "type": "t_mapping(t_bytes32,t_struct(AddressSet)8661_storage)", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol:22" + }, + { + "contract": "AccessControlEnumerableUpgradeable", + "label": "__gap", + "type": "t_array(t_uint256)49_storage", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol:76" + }, + { + "contract": "SkaleManagerClient", + "label": "contractManagerOfSkaleManager", + "type": "t_contract(IContractManager)10382", + "src": "contracts/mainnet/SkaleManagerClient.sol:37" + }, + { + "contract": "Twin", + "label": "messageProxy", + "type": "t_contract(IMessageProxyForMainnet)9795", + "src": "contracts/mainnet/Twin.sol:38" + }, + { + "contract": "Twin", + "label": "schainLinks", + "type": "t_mapping(t_bytes32,t_address)", + "src": "contracts/mainnet/Twin.sol:39" + }, + { + "contract": "DepositBox", + "label": "linker", + "type": "t_contract(ILinker)9750", + "src": "contracts/mainnet/DepositBox.sol:36" + }, + { + "contract": "DepositBox", + "label": "_automaticDeploy", + "type": "t_mapping(t_bytes32,t_bool)", + "src": "contracts/mainnet/DepositBox.sol:39" + }, + { + "contract": "DepositBoxERC721", + "label": "_deprecatedSchainToERC721", + "type": "t_mapping(t_bytes32,t_mapping(t_address,t_bool))", + "src": "contracts/mainnet/DepositBoxes/DepositBoxERC721.sol:46" + }, + { + "contract": "DepositBoxERC721", + "label": "transferredAmount", + "type": "t_mapping(t_address,t_mapping(t_uint256,t_bytes32))", + "src": "contracts/mainnet/DepositBoxes/DepositBoxERC721.sol:47" + }, + { + "contract": "DepositBoxERC721", + "label": "_schainToERC721", + "type": "t_mapping(t_bytes32,t_struct(AddressSet)8661_storage)", + "src": "contracts/mainnet/DepositBoxes/DepositBoxERC721.sol:48" + } + ], + "types": { + "t_mapping(t_bytes32,t_mapping(t_address,t_bool))": { + "label": "mapping(bytes32 => mapping(address => bool))" + }, + "t_bytes32": { + "label": "bytes32" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)" + }, + "t_address": { + "label": "address" + }, + "t_bool": { + "label": "bool" + }, + "t_mapping(t_address,t_mapping(t_uint256,t_bytes32))": { + "label": "mapping(address => mapping(uint256 => bytes32))" + }, + "t_mapping(t_uint256,t_bytes32)": { + "label": "mapping(uint256 => bytes32)" + }, + "t_uint256": { + "label": "uint256" + }, + "t_mapping(t_bytes32,t_struct(AddressSet)8661_storage)": { + "label": "mapping(bytes32 => struct EnumerableSetUpgradeable.AddressSet)" + }, + "t_struct(AddressSet)8661_storage": { + "label": "struct EnumerableSetUpgradeable.AddressSet", + "members": [ + { + "label": "_inner", + "type": "t_struct(Set)8360_storage" + } + ] + }, + "t_struct(Set)8360_storage": { + "label": "struct EnumerableSetUpgradeable.Set", + "members": [ + { + "label": "_values", + "type": "t_array(t_bytes32)dyn_storage" + }, + { + "label": "_indexes", + "type": "t_mapping(t_bytes32,t_uint256)" + } + ] + }, + "t_array(t_bytes32)dyn_storage": { + "label": "bytes32[]" + }, + "t_mapping(t_bytes32,t_uint256)": { + "label": "mapping(bytes32 => uint256)" + }, + "t_contract(ILinker)9750": { + "label": "contract ILinker" + }, + "t_mapping(t_bytes32,t_bool)": { + "label": "mapping(bytes32 => bool)" + }, + "t_contract(IMessageProxyForMainnet)9795": { + "label": "contract IMessageProxyForMainnet" + }, + "t_mapping(t_bytes32,t_address)": { + "label": "mapping(bytes32 => address)" + }, + "t_contract(IContractManager)10382": { + "label": "contract IContractManager" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]" + }, + "t_mapping(t_bytes32,t_struct(RoleData)179_storage)": { + "label": "mapping(bytes32 => struct AccessControlUpgradeable.RoleData)" + }, + "t_struct(RoleData)179_storage": { + "label": "struct AccessControlUpgradeable.RoleData", + "members": [ + { + "label": "members", + "type": "t_mapping(t_address,t_bool)" + }, + { + "label": "adminRole", + "type": "t_bytes32" + } + ] + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]" + }, + "t_uint8": { + "label": "uint8" + } + } + } + }, + "59a902dda9624a6536c254f82d8d63a88e20e802815828aecdf3c89b25190c5c": { + "address": "0xBc03C79991f6a6486B5187ad91853626c9686bF2", + "txHash": "0x86d04f1be9820d868e2ee679a6219dd23b2bb277ed7c87433b5d0a01552e735f", + "layout": { + "storage": [ + { + "contract": "Initializable", + "label": "_initialized", + "type": "t_uint8", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:62" + }, + { + "contract": "Initializable", + "label": "_initializing", + "type": "t_bool", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:67" + }, + { + "contract": "ContextUpgradeable", + "label": "__gap", + "type": "t_array(t_uint256)50_storage", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" + }, + { + "contract": "ERC165Upgradeable", + "label": "__gap", + "type": "t_array(t_uint256)50_storage", + "src": "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol:41" + }, + { + "contract": "AccessControlUpgradeable", + "label": "_roles", + "type": "t_mapping(t_bytes32,t_struct(RoleData)179_storage)", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:61" + }, + { + "contract": "AccessControlUpgradeable", + "label": "__gap", + "type": "t_array(t_uint256)49_storage", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:259" + }, + { + "contract": "AccessControlEnumerableUpgradeable", + "label": "_roleMembers", + "type": "t_mapping(t_bytes32,t_struct(AddressSet)8661_storage)", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol:22" + }, + { + "contract": "AccessControlEnumerableUpgradeable", + "label": "__gap", + "type": "t_array(t_uint256)49_storage", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol:76" + }, + { + "contract": "SkaleManagerClient", + "label": "contractManagerOfSkaleManager", + "type": "t_contract(IContractManager)10382", + "src": "contracts/mainnet/SkaleManagerClient.sol:37" + }, + { + "contract": "Twin", + "label": "messageProxy", + "type": "t_contract(IMessageProxyForMainnet)9795", + "src": "contracts/mainnet/Twin.sol:38" + }, + { + "contract": "Twin", + "label": "schainLinks", + "type": "t_mapping(t_bytes32,t_address)", + "src": "contracts/mainnet/Twin.sol:39" + }, + { + "contract": "DepositBox", + "label": "linker", + "type": "t_contract(ILinker)9750", + "src": "contracts/mainnet/DepositBox.sol:36" + }, + { + "contract": "DepositBox", + "label": "_automaticDeploy", + "type": "t_mapping(t_bytes32,t_bool)", + "src": "contracts/mainnet/DepositBox.sol:39" + }, + { + "contract": "ERC1155ReceiverUpgradeable", + "label": "__gap", + "type": "t_array(t_uint256)50_storage", + "src": "@openzeppelin/contracts-upgradeable/token/ERC1155/utils/ERC1155ReceiverUpgradeable.sol:31" + }, + { + "contract": "DepositBoxERC1155", + "label": "_deprecatedSchainToERC1155", + "type": "t_mapping(t_bytes32,t_mapping(t_address,t_bool))", + "src": "contracts/mainnet/DepositBoxes/DepositBoxERC1155.sol:49" + }, + { + "contract": "DepositBoxERC1155", + "label": "transferredAmount", + "type": "t_mapping(t_bytes32,t_mapping(t_address,t_mapping(t_uint256,t_uint256)))", + "src": "contracts/mainnet/DepositBoxes/DepositBoxERC1155.sol:50" + }, + { + "contract": "DepositBoxERC1155", + "label": "_schainToERC1155", + "type": "t_mapping(t_bytes32,t_struct(AddressSet)8661_storage)", + "src": "contracts/mainnet/DepositBoxes/DepositBoxERC1155.sol:51" + } + ], + "types": { + "t_mapping(t_bytes32,t_mapping(t_address,t_bool))": { + "label": "mapping(bytes32 => mapping(address => bool))" + }, + "t_bytes32": { + "label": "bytes32" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)" + }, + "t_address": { + "label": "address" + }, + "t_bool": { + "label": "bool" + }, + "t_mapping(t_bytes32,t_mapping(t_address,t_mapping(t_uint256,t_uint256)))": { + "label": "mapping(bytes32 => mapping(address => mapping(uint256 => uint256)))" + }, + "t_mapping(t_address,t_mapping(t_uint256,t_uint256))": { + "label": "mapping(address => mapping(uint256 => uint256))" + }, + "t_mapping(t_uint256,t_uint256)": { + "label": "mapping(uint256 => uint256)" + }, + "t_uint256": { + "label": "uint256" + }, + "t_mapping(t_bytes32,t_struct(AddressSet)8661_storage)": { + "label": "mapping(bytes32 => struct EnumerableSetUpgradeable.AddressSet)" + }, + "t_struct(AddressSet)8661_storage": { + "label": "struct EnumerableSetUpgradeable.AddressSet", + "members": [ + { + "label": "_inner", + "type": "t_struct(Set)8360_storage" + } + ] + }, + "t_struct(Set)8360_storage": { + "label": "struct EnumerableSetUpgradeable.Set", + "members": [ + { + "label": "_values", + "type": "t_array(t_bytes32)dyn_storage" + }, + { + "label": "_indexes", + "type": "t_mapping(t_bytes32,t_uint256)" + } + ] + }, + "t_array(t_bytes32)dyn_storage": { + "label": "bytes32[]" + }, + "t_mapping(t_bytes32,t_uint256)": { + "label": "mapping(bytes32 => uint256)" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]" + }, + "t_contract(ILinker)9750": { + "label": "contract ILinker" + }, + "t_mapping(t_bytes32,t_bool)": { + "label": "mapping(bytes32 => bool)" + }, + "t_contract(IMessageProxyForMainnet)9795": { + "label": "contract IMessageProxyForMainnet" + }, + "t_mapping(t_bytes32,t_address)": { + "label": "mapping(bytes32 => address)" + }, + "t_contract(IContractManager)10382": { + "label": "contract IContractManager" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]" + }, + "t_mapping(t_bytes32,t_struct(RoleData)179_storage)": { + "label": "mapping(bytes32 => struct AccessControlUpgradeable.RoleData)" + }, + "t_struct(RoleData)179_storage": { + "label": "struct AccessControlUpgradeable.RoleData", + "members": [ + { + "label": "members", + "type": "t_mapping(t_address,t_bool)" + }, + { + "label": "adminRole", + "type": "t_bytes32" + } + ] + }, + "t_uint8": { + "label": "uint8" + } + } + } + }, + "1a9001822d60ba0c7aa9c80d35572bb16c40a7103cc7352818334cbdb96df86b": { + "address": "0xCe4ceF453a2D7071B845e36a2E1bf096fba6eEeA", + "txHash": "0x3b4f7db78d229b2dcd260802f653628f207f7bfd8738994b66ae119c15f67696", + "layout": { + "storage": [ + { + "contract": "Initializable", + "label": "_initialized", + "type": "t_uint8", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:62" + }, + { + "contract": "Initializable", + "label": "_initializing", + "type": "t_bool", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:67" + }, + { + "contract": "ContextUpgradeable", + "label": "__gap", + "type": "t_array(t_uint256)50_storage", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" + }, + { + "contract": "ERC165Upgradeable", + "label": "__gap", + "type": "t_array(t_uint256)50_storage", + "src": "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol:41" + }, + { + "contract": "AccessControlUpgradeable", + "label": "_roles", + "type": "t_mapping(t_bytes32,t_struct(RoleData)179_storage)", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:61" + }, + { + "contract": "AccessControlUpgradeable", + "label": "__gap", + "type": "t_array(t_uint256)49_storage", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:259" + }, + { + "contract": "AccessControlEnumerableUpgradeable", + "label": "_roleMembers", + "type": "t_mapping(t_bytes32,t_struct(AddressSet)8661_storage)", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol:22" + }, + { + "contract": "AccessControlEnumerableUpgradeable", + "label": "__gap", + "type": "t_array(t_uint256)49_storage", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol:76" + }, + { + "contract": "SkaleManagerClient", + "label": "contractManagerOfSkaleManager", + "type": "t_contract(IContractManager)10382", + "src": "contracts/mainnet/SkaleManagerClient.sol:37" + }, + { + "contract": "Twin", + "label": "messageProxy", + "type": "t_contract(IMessageProxyForMainnet)9795", + "src": "contracts/mainnet/Twin.sol:38" + }, + { + "contract": "Twin", + "label": "schainLinks", + "type": "t_mapping(t_bytes32,t_address)", + "src": "contracts/mainnet/Twin.sol:39" + }, + { + "contract": "DepositBox", + "label": "linker", + "type": "t_contract(ILinker)9750", + "src": "contracts/mainnet/DepositBox.sol:36" + }, + { + "contract": "DepositBox", + "label": "_automaticDeploy", + "type": "t_mapping(t_bytes32,t_bool)", + "src": "contracts/mainnet/DepositBox.sol:39" + }, + { + "contract": "DepositBoxERC721", + "label": "_deprecatedSchainToERC721", + "type": "t_mapping(t_bytes32,t_mapping(t_address,t_bool))", + "src": "contracts/mainnet/DepositBoxes/DepositBoxERC721.sol:46" + }, + { + "contract": "DepositBoxERC721", + "label": "transferredAmount", + "type": "t_mapping(t_address,t_mapping(t_uint256,t_bytes32))", + "src": "contracts/mainnet/DepositBoxes/DepositBoxERC721.sol:47" + }, + { + "contract": "DepositBoxERC721", + "label": "_schainToERC721", + "type": "t_mapping(t_bytes32,t_struct(AddressSet)8661_storage)", + "src": "contracts/mainnet/DepositBoxes/DepositBoxERC721.sol:48" + } + ], + "types": { + "t_mapping(t_bytes32,t_mapping(t_address,t_bool))": { + "label": "mapping(bytes32 => mapping(address => bool))" + }, + "t_bytes32": { + "label": "bytes32" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)" + }, + "t_address": { + "label": "address" + }, + "t_bool": { + "label": "bool" + }, + "t_mapping(t_address,t_mapping(t_uint256,t_bytes32))": { + "label": "mapping(address => mapping(uint256 => bytes32))" + }, + "t_mapping(t_uint256,t_bytes32)": { + "label": "mapping(uint256 => bytes32)" + }, + "t_uint256": { + "label": "uint256" + }, + "t_mapping(t_bytes32,t_struct(AddressSet)8661_storage)": { + "label": "mapping(bytes32 => struct EnumerableSetUpgradeable.AddressSet)" + }, + "t_struct(AddressSet)8661_storage": { + "label": "struct EnumerableSetUpgradeable.AddressSet", + "members": [ + { + "label": "_inner", + "type": "t_struct(Set)8360_storage" + } + ] + }, + "t_struct(Set)8360_storage": { + "label": "struct EnumerableSetUpgradeable.Set", + "members": [ + { + "label": "_values", + "type": "t_array(t_bytes32)dyn_storage" + }, + { + "label": "_indexes", + "type": "t_mapping(t_bytes32,t_uint256)" + } + ] + }, + "t_array(t_bytes32)dyn_storage": { + "label": "bytes32[]" + }, + "t_mapping(t_bytes32,t_uint256)": { + "label": "mapping(bytes32 => uint256)" + }, + "t_contract(ILinker)9750": { + "label": "contract ILinker" + }, + "t_mapping(t_bytes32,t_bool)": { + "label": "mapping(bytes32 => bool)" + }, + "t_contract(IMessageProxyForMainnet)9795": { + "label": "contract IMessageProxyForMainnet" + }, + "t_mapping(t_bytes32,t_address)": { + "label": "mapping(bytes32 => address)" + }, + "t_contract(IContractManager)10382": { + "label": "contract IContractManager" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]" + }, + "t_mapping(t_bytes32,t_struct(RoleData)179_storage)": { + "label": "mapping(bytes32 => struct AccessControlUpgradeable.RoleData)" + }, + "t_struct(RoleData)179_storage": { + "label": "struct AccessControlUpgradeable.RoleData", + "members": [ + { + "label": "members", + "type": "t_mapping(t_address,t_bool)" + }, + { + "label": "adminRole", + "type": "t_bytes32" + } + ] + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]" + }, + "t_uint8": { + "label": "uint8" + } + } + } + }, + "6578b5d8690e7ec2ffe9df16ae35a3c78ef74be2bd5b57fe2e6e406e91b2ab42": { + "address": "0xfE6faFAC88150A23D946E53E9e2285aAB98A0d90", + "txHash": "0x387fc8037a21cba5c767786d79d81c7cddfa81b605b120e68a0b8c2dc0971500", + "layout": { + "storage": [ + { + "contract": "Initializable", + "label": "_initialized", + "type": "t_uint8", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:62" + }, + { + "contract": "Initializable", + "label": "_initializing", + "type": "t_bool", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:67" + }, + { + "contract": "ContextUpgradeable", + "label": "__gap", + "type": "t_array(t_uint256)50_storage", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" + }, + { + "contract": "ERC165Upgradeable", + "label": "__gap", + "type": "t_array(t_uint256)50_storage", + "src": "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol:41" + }, + { + "contract": "AccessControlUpgradeable", + "label": "_roles", + "type": "t_mapping(t_bytes32,t_struct(RoleData)179_storage)", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:61" + }, + { + "contract": "AccessControlUpgradeable", + "label": "__gap", + "type": "t_array(t_uint256)49_storage", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:259" + }, + { + "contract": "AccessControlEnumerableUpgradeable", + "label": "_roleMembers", + "type": "t_mapping(t_bytes32,t_struct(AddressSet)8661_storage)", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol:22" + }, + { + "contract": "AccessControlEnumerableUpgradeable", + "label": "__gap", + "type": "t_array(t_uint256)49_storage", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol:76" + }, + { + "contract": "SkaleManagerClient", + "label": "contractManagerOfSkaleManager", + "type": "t_contract(IContractManager)10439", + "src": "contracts/mainnet/SkaleManagerClient.sol:37" + }, + { + "contract": "Twin", + "label": "messageProxy", + "type": "t_contract(IMessageProxyForMainnet)9852", + "src": "contracts/mainnet/Twin.sol:38" + }, + { + "contract": "Twin", + "label": "schainLinks", + "type": "t_mapping(t_bytes32,t_address)", + "src": "contracts/mainnet/Twin.sol:39" + }, + { + "contract": "DepositBox", + "label": "linker", + "type": "t_contract(ILinker)9807", + "src": "contracts/mainnet/DepositBox.sol:36" + }, + { + "contract": "DepositBox", + "label": "_automaticDeploy", + "type": "t_mapping(t_bytes32,t_bool)", + "src": "contracts/mainnet/DepositBox.sol:39" + }, + { + "contract": "DepositBoxEth", + "label": "approveTransfers", + "type": "t_mapping(t_address,t_uint256)", + "src": "contracts/mainnet/DepositBoxes/DepositBoxEth.sol:39" + }, + { + "contract": "DepositBoxEth", + "label": "transferredAmount", + "type": "t_mapping(t_bytes32,t_uint256)", + "src": "contracts/mainnet/DepositBoxes/DepositBoxEth.sol:41" + }, + { + "contract": "DepositBoxEth", + "label": "activeEthTransfers", + "type": "t_mapping(t_bytes32,t_bool)", + "src": "contracts/mainnet/DepositBoxes/DepositBoxEth.sol:43" + } + ], + "types": { + "t_mapping(t_address,t_uint256)": { + "label": "mapping(address => uint256)" + }, + "t_address": { + "label": "address" + }, + "t_uint256": { + "label": "uint256" + }, + "t_mapping(t_bytes32,t_uint256)": { + "label": "mapping(bytes32 => uint256)" + }, + "t_bytes32": { + "label": "bytes32" + }, + "t_mapping(t_bytes32,t_bool)": { + "label": "mapping(bytes32 => bool)" + }, + "t_bool": { + "label": "bool" + }, + "t_contract(ILinker)9807": { + "label": "contract ILinker" + }, + "t_contract(IMessageProxyForMainnet)9852": { + "label": "contract IMessageProxyForMainnet" + }, + "t_mapping(t_bytes32,t_address)": { + "label": "mapping(bytes32 => address)" + }, + "t_contract(IContractManager)10439": { + "label": "contract IContractManager" + }, + "t_mapping(t_bytes32,t_struct(AddressSet)8661_storage)": { + "label": "mapping(bytes32 => struct EnumerableSetUpgradeable.AddressSet)" + }, + "t_struct(AddressSet)8661_storage": { + "label": "struct EnumerableSetUpgradeable.AddressSet", + "members": [ + { + "label": "_inner", + "type": "t_struct(Set)8360_storage" + } + ] + }, + "t_struct(Set)8360_storage": { + "label": "struct EnumerableSetUpgradeable.Set", + "members": [ + { + "label": "_values", + "type": "t_array(t_bytes32)dyn_storage" + }, + { + "label": "_indexes", + "type": "t_mapping(t_bytes32,t_uint256)" + } + ] + }, + "t_array(t_bytes32)dyn_storage": { + "label": "bytes32[]" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]" + }, + "t_mapping(t_bytes32,t_struct(RoleData)179_storage)": { + "label": "mapping(bytes32 => struct AccessControlUpgradeable.RoleData)" + }, + "t_struct(RoleData)179_storage": { + "label": "struct AccessControlUpgradeable.RoleData", + "members": [ + { + "label": "members", + "type": "t_mapping(t_address,t_bool)" + }, + { + "label": "adminRole", + "type": "t_bytes32" + } + ] + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]" + }, + "t_uint8": { + "label": "uint8" + } + } + } + }, + "ac3f405ee46c32af859f71eaa5396893b27253503945319ff602239e674db044": { + "address": "0x778B105215e59e4731CcBDcB0A54C367FD3897a1", + "txHash": "0xad9db4211042adf0653460ec29e416aa5f50e3c94fffec70889f552468e6dcf1", + "layout": { + "storage": [ + { + "contract": "Initializable", + "label": "_initialized", + "type": "t_uint8", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:62" + }, + { + "contract": "Initializable", + "label": "_initializing", + "type": "t_bool", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:67" + }, + { + "contract": "ContextUpgradeable", + "label": "__gap", + "type": "t_array(t_uint256)50_storage", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" + }, + { + "contract": "ERC165Upgradeable", + "label": "__gap", + "type": "t_array(t_uint256)50_storage", + "src": "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol:41" + }, + { + "contract": "AccessControlUpgradeable", + "label": "_roles", + "type": "t_mapping(t_bytes32,t_struct(RoleData)179_storage)", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:61" + }, + { + "contract": "AccessControlUpgradeable", + "label": "__gap", + "type": "t_array(t_uint256)49_storage", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:259" + }, + { + "contract": "AccessControlEnumerableUpgradeable", + "label": "_roleMembers", + "type": "t_mapping(t_bytes32,t_struct(AddressSet)8661_storage)", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol:22" + }, + { + "contract": "AccessControlEnumerableUpgradeable", + "label": "__gap", + "type": "t_array(t_uint256)49_storage", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol:76" + }, + { + "contract": "SkaleManagerClient", + "label": "contractManagerOfSkaleManager", + "type": "t_contract(IContractManager)10439", + "src": "contracts/mainnet/SkaleManagerClient.sol:37" + }, + { + "contract": "Twin", + "label": "messageProxy", + "type": "t_contract(IMessageProxyForMainnet)9852", + "src": "contracts/mainnet/Twin.sol:38" + }, + { + "contract": "Twin", + "label": "schainLinks", + "type": "t_mapping(t_bytes32,t_address)", + "src": "contracts/mainnet/Twin.sol:39" + }, + { + "contract": "DepositBox", + "label": "linker", + "type": "t_contract(ILinker)9807", + "src": "contracts/mainnet/DepositBox.sol:36" + }, + { + "contract": "DepositBox", + "label": "_automaticDeploy", + "type": "t_mapping(t_bytes32,t_bool)", + "src": "contracts/mainnet/DepositBox.sol:39" + }, + { + "contract": "DepositBoxERC20", + "label": "_deprecatedSchainToERC20", + "type": "t_mapping(t_bytes32,t_mapping(t_address,t_bool))", + "src": "contracts/mainnet/DepositBoxes/DepositBoxERC20.sol:84" + }, + { + "contract": "DepositBoxERC20", + "label": "transferredAmount", + "type": "t_mapping(t_bytes32,t_mapping(t_address,t_uint256))", + "src": "contracts/mainnet/DepositBoxes/DepositBoxERC20.sol:85" + }, + { + "contract": "DepositBoxERC20", + "label": "_schainToERC20", + "type": "t_mapping(t_bytes32,t_struct(AddressSet)8661_storage)", + "src": "contracts/mainnet/DepositBoxes/DepositBoxERC20.sol:86" + }, + { + "contract": "DepositBoxERC20", + "label": "_delayConfig", + "type": "t_mapping(t_bytes32,t_struct(DelayConfig)15881_storage)", + "src": "contracts/mainnet/DepositBoxes/DepositBoxERC20.sol:90" + }, + { + "contract": "DepositBoxERC20", + "label": "delayedTransfersSize", + "type": "t_uint256", + "src": "contracts/mainnet/DepositBoxes/DepositBoxERC20.sol:92" + }, + { + "contract": "DepositBoxERC20", + "label": "delayedTransfers", + "type": "t_mapping(t_uint256,t_struct(DelayedTransfer)15869_storage)", + "src": "contracts/mainnet/DepositBoxes/DepositBoxERC20.sol:94" + }, + { + "contract": "DepositBoxERC20", + "label": "delayedTransfersByReceiver", + "type": "t_mapping(t_address,t_struct(Bytes32Deque)8027_storage)", + "src": "contracts/mainnet/DepositBoxes/DepositBoxERC20.sol:96" + } + ], + "types": { + "t_mapping(t_bytes32,t_mapping(t_address,t_bool))": { + "label": "mapping(bytes32 => mapping(address => bool))" + }, + "t_bytes32": { + "label": "bytes32" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)" + }, + "t_address": { + "label": "address" + }, + "t_bool": { + "label": "bool" + }, + "t_mapping(t_bytes32,t_mapping(t_address,t_uint256))": { + "label": "mapping(bytes32 => mapping(address => uint256))" + }, + "t_mapping(t_address,t_uint256)": { + "label": "mapping(address => uint256)" + }, + "t_uint256": { + "label": "uint256" + }, + "t_mapping(t_bytes32,t_struct(AddressSet)8661_storage)": { + "label": "mapping(bytes32 => struct EnumerableSetUpgradeable.AddressSet)" + }, + "t_struct(AddressSet)8661_storage": { + "label": "struct EnumerableSetUpgradeable.AddressSet", + "members": [ + { + "label": "_inner", + "type": "t_struct(Set)8360_storage" + } + ] + }, + "t_struct(Set)8360_storage": { + "label": "struct EnumerableSetUpgradeable.Set", + "members": [ + { + "label": "_values", + "type": "t_array(t_bytes32)dyn_storage" + }, + { + "label": "_indexes", + "type": "t_mapping(t_bytes32,t_uint256)" + } + ] + }, + "t_array(t_bytes32)dyn_storage": { + "label": "bytes32[]" + }, + "t_mapping(t_bytes32,t_uint256)": { + "label": "mapping(bytes32 => uint256)" + }, + "t_mapping(t_bytes32,t_struct(DelayConfig)15881_storage)": { + "label": "mapping(bytes32 => struct DepositBoxERC20.DelayConfig)" + }, + "t_struct(DelayConfig)15881_storage": { + "label": "struct DepositBoxERC20.DelayConfig", + "members": [ + { + "label": "bigTransferThreshold", + "type": "t_mapping(t_address,t_uint256)" + }, + { + "label": "trustedReceivers", + "type": "t_struct(AddressSet)8661_storage" + }, + { + "label": "transferDelay", + "type": "t_uint256" + }, + { + "label": "arbitrageDuration", + "type": "t_uint256" + } + ] + }, + "t_mapping(t_uint256,t_struct(DelayedTransfer)15869_storage)": { + "label": "mapping(uint256 => struct DepositBoxERC20.DelayedTransfer)" + }, + "t_struct(DelayedTransfer)15869_storage": { + "label": "struct DepositBoxERC20.DelayedTransfer", + "members": [ + { + "label": "receiver", + "type": "t_address" + }, + { + "label": "schainHash", + "type": "t_bytes32" + }, + { + "label": "token", + "type": "t_address" + }, + { + "label": "amount", + "type": "t_uint256" + }, + { + "label": "untilTimestamp", + "type": "t_uint256" + }, + { + "label": "status", + "type": "t_enum(DelayedTransferStatus)15855" + } + ] + }, + "t_enum(DelayedTransferStatus)15855": { + "label": "enum DepositBoxERC20.DelayedTransferStatus", + "members": [ + "DELAYED", + "ARBITRAGE", + "COMPLETED" + ] + }, + "t_mapping(t_address,t_struct(Bytes32Deque)8027_storage)": { + "label": "mapping(address => struct DoubleEndedQueueUpgradeable.Bytes32Deque)" + }, + "t_struct(Bytes32Deque)8027_storage": { + "label": "struct DoubleEndedQueueUpgradeable.Bytes32Deque", + "members": [ + { + "label": "_begin", + "type": "t_int128" + }, + { + "label": "_end", + "type": "t_int128" + }, + { + "label": "_data", + "type": "t_mapping(t_int128,t_bytes32)" + } + ] + }, + "t_int128": { + "label": "int128" + }, + "t_mapping(t_int128,t_bytes32)": { + "label": "mapping(int128 => bytes32)" + }, + "t_contract(ILinker)9807": { + "label": "contract ILinker" + }, + "t_mapping(t_bytes32,t_bool)": { + "label": "mapping(bytes32 => bool)" + }, + "t_contract(IMessageProxyForMainnet)9852": { + "label": "contract IMessageProxyForMainnet" + }, + "t_mapping(t_bytes32,t_address)": { + "label": "mapping(bytes32 => address)" + }, + "t_contract(IContractManager)10439": { + "label": "contract IContractManager" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]" + }, + "t_mapping(t_bytes32,t_struct(RoleData)179_storage)": { + "label": "mapping(bytes32 => struct AccessControlUpgradeable.RoleData)" + }, + "t_struct(RoleData)179_storage": { + "label": "struct AccessControlUpgradeable.RoleData", + "members": [ + { + "label": "members", + "type": "t_mapping(t_address,t_bool)" + }, + { + "label": "adminRole", + "type": "t_bytes32" + } + ] + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]" + }, + "t_uint8": { + "label": "uint8" + } + } + } + }, + "2183964d94b999aff896613761eda57f8a060c6cd3c56e052f9a3a419c56181f": { + "address": "0xa66b813b2e32EEb82D4dafB5e784471cdba452E8", + "txHash": "0xb50b79035ad992d65a425e3388ba35c11851843ffb9b08e9ab75d0cc1e62b68d", + "layout": { + "storage": [ + { + "contract": "Initializable", + "label": "_initialized", + "type": "t_uint8", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:62" + }, + { + "contract": "Initializable", + "label": "_initializing", + "type": "t_bool", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:67" + }, + { + "contract": "ContextUpgradeable", + "label": "__gap", + "type": "t_array(t_uint256)50_storage", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" + }, + { + "contract": "ERC165Upgradeable", + "label": "__gap", + "type": "t_array(t_uint256)50_storage", + "src": "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol:41" + }, + { + "contract": "AccessControlUpgradeable", + "label": "_roles", + "type": "t_mapping(t_bytes32,t_struct(RoleData)179_storage)", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:61" + }, + { + "contract": "AccessControlUpgradeable", + "label": "__gap", + "type": "t_array(t_uint256)49_storage", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:259" + }, + { + "contract": "AccessControlEnumerableUpgradeable", + "label": "_roleMembers", + "type": "t_mapping(t_bytes32,t_struct(AddressSet)8661_storage)", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol:22" + }, + { + "contract": "AccessControlEnumerableUpgradeable", + "label": "__gap", + "type": "t_array(t_uint256)49_storage", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol:76" + }, + { + "contract": "SkaleManagerClient", + "label": "contractManagerOfSkaleManager", + "type": "t_contract(IContractManager)10439", + "src": "contracts/mainnet/SkaleManagerClient.sol:37" + }, + { + "contract": "Twin", + "label": "messageProxy", + "type": "t_contract(IMessageProxyForMainnet)9852", + "src": "contracts/mainnet/Twin.sol:38" + }, + { + "contract": "Twin", + "label": "schainLinks", + "type": "t_mapping(t_bytes32,t_address)", + "src": "contracts/mainnet/Twin.sol:39" + }, + { + "contract": "DepositBox", + "label": "linker", + "type": "t_contract(ILinker)9807", + "src": "contracts/mainnet/DepositBox.sol:36" + }, + { + "contract": "DepositBox", + "label": "_automaticDeploy", + "type": "t_mapping(t_bytes32,t_bool)", + "src": "contracts/mainnet/DepositBox.sol:39" + }, + { + "contract": "DepositBoxERC721", + "label": "_deprecatedSchainToERC721", + "type": "t_mapping(t_bytes32,t_mapping(t_address,t_bool))", + "src": "contracts/mainnet/DepositBoxes/DepositBoxERC721.sol:46" + }, + { + "contract": "DepositBoxERC721", + "label": "transferredAmount", + "type": "t_mapping(t_address,t_mapping(t_uint256,t_bytes32))", + "src": "contracts/mainnet/DepositBoxes/DepositBoxERC721.sol:47" + }, + { + "contract": "DepositBoxERC721", + "label": "_schainToERC721", + "type": "t_mapping(t_bytes32,t_struct(AddressSet)8661_storage)", + "src": "contracts/mainnet/DepositBoxes/DepositBoxERC721.sol:48" + } + ], + "types": { + "t_mapping(t_bytes32,t_mapping(t_address,t_bool))": { + "label": "mapping(bytes32 => mapping(address => bool))" + }, + "t_bytes32": { + "label": "bytes32" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)" + }, + "t_address": { + "label": "address" + }, + "t_bool": { + "label": "bool" + }, + "t_mapping(t_address,t_mapping(t_uint256,t_bytes32))": { + "label": "mapping(address => mapping(uint256 => bytes32))" + }, + "t_mapping(t_uint256,t_bytes32)": { + "label": "mapping(uint256 => bytes32)" + }, + "t_uint256": { + "label": "uint256" + }, + "t_mapping(t_bytes32,t_struct(AddressSet)8661_storage)": { + "label": "mapping(bytes32 => struct EnumerableSetUpgradeable.AddressSet)" + }, + "t_struct(AddressSet)8661_storage": { + "label": "struct EnumerableSetUpgradeable.AddressSet", + "members": [ + { + "label": "_inner", + "type": "t_struct(Set)8360_storage" + } + ] + }, + "t_struct(Set)8360_storage": { + "label": "struct EnumerableSetUpgradeable.Set", + "members": [ + { + "label": "_values", + "type": "t_array(t_bytes32)dyn_storage" + }, + { + "label": "_indexes", + "type": "t_mapping(t_bytes32,t_uint256)" + } + ] + }, + "t_array(t_bytes32)dyn_storage": { + "label": "bytes32[]" + }, + "t_mapping(t_bytes32,t_uint256)": { + "label": "mapping(bytes32 => uint256)" + }, + "t_contract(ILinker)9807": { + "label": "contract ILinker" + }, + "t_mapping(t_bytes32,t_bool)": { + "label": "mapping(bytes32 => bool)" + }, + "t_contract(IMessageProxyForMainnet)9852": { + "label": "contract IMessageProxyForMainnet" + }, + "t_mapping(t_bytes32,t_address)": { + "label": "mapping(bytes32 => address)" + }, + "t_contract(IContractManager)10439": { + "label": "contract IContractManager" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]" + }, + "t_mapping(t_bytes32,t_struct(RoleData)179_storage)": { + "label": "mapping(bytes32 => struct AccessControlUpgradeable.RoleData)" + }, + "t_struct(RoleData)179_storage": { + "label": "struct AccessControlUpgradeable.RoleData", + "members": [ + { + "label": "members", + "type": "t_mapping(t_address,t_bool)" + }, + { + "label": "adminRole", + "type": "t_bytes32" + } + ] + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]" + }, + "t_uint8": { + "label": "uint8" + } + } + } + }, + "b5f72a6b685f6b0ebc2de40214484e89b11304f2e53eaa1e9402498b3cde0b86": { + "address": "0x9429952791A01c35E715826f34727E885A2b2f09", + "txHash": "0x13b38089d2d8378c8dbccf93220b30b802bab74f148f65a1539cd522228b5160", + "layout": { + "storage": [ + { + "contract": "Initializable", + "label": "_initialized", + "type": "t_uint8", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:62" + }, + { + "contract": "Initializable", + "label": "_initializing", + "type": "t_bool", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:67" + }, + { + "contract": "ContextUpgradeable", + "label": "__gap", + "type": "t_array(t_uint256)50_storage", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" + }, + { + "contract": "ERC165Upgradeable", + "label": "__gap", + "type": "t_array(t_uint256)50_storage", + "src": "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol:41" + }, + { + "contract": "AccessControlUpgradeable", + "label": "_roles", + "type": "t_mapping(t_bytes32,t_struct(RoleData)179_storage)", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:61" + }, + { + "contract": "AccessControlUpgradeable", + "label": "__gap", + "type": "t_array(t_uint256)49_storage", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:259" + }, + { + "contract": "AccessControlEnumerableUpgradeable", + "label": "_roleMembers", + "type": "t_mapping(t_bytes32,t_struct(AddressSet)8661_storage)", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol:22" + }, + { + "contract": "AccessControlEnumerableUpgradeable", + "label": "__gap", + "type": "t_array(t_uint256)49_storage", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol:76" + }, + { + "contract": "SkaleManagerClient", + "label": "contractManagerOfSkaleManager", + "type": "t_contract(IContractManager)10439", + "src": "contracts/mainnet/SkaleManagerClient.sol:37" + }, + { + "contract": "Twin", + "label": "messageProxy", + "type": "t_contract(IMessageProxyForMainnet)9852", + "src": "contracts/mainnet/Twin.sol:38" + }, + { + "contract": "Twin", + "label": "schainLinks", + "type": "t_mapping(t_bytes32,t_address)", + "src": "contracts/mainnet/Twin.sol:39" + }, + { + "contract": "DepositBox", + "label": "linker", + "type": "t_contract(ILinker)9807", + "src": "contracts/mainnet/DepositBox.sol:36" + }, + { + "contract": "DepositBox", + "label": "_automaticDeploy", + "type": "t_mapping(t_bytes32,t_bool)", + "src": "contracts/mainnet/DepositBox.sol:39" + }, + { + "contract": "ERC1155ReceiverUpgradeable", + "label": "__gap", + "type": "t_array(t_uint256)50_storage", + "src": "@openzeppelin/contracts-upgradeable/token/ERC1155/utils/ERC1155ReceiverUpgradeable.sol:31" + }, + { + "contract": "DepositBoxERC1155", + "label": "_deprecatedSchainToERC1155", + "type": "t_mapping(t_bytes32,t_mapping(t_address,t_bool))", + "src": "contracts/mainnet/DepositBoxes/DepositBoxERC1155.sol:49" + }, + { + "contract": "DepositBoxERC1155", + "label": "transferredAmount", + "type": "t_mapping(t_bytes32,t_mapping(t_address,t_mapping(t_uint256,t_uint256)))", + "src": "contracts/mainnet/DepositBoxes/DepositBoxERC1155.sol:50" + }, + { + "contract": "DepositBoxERC1155", + "label": "_schainToERC1155", + "type": "t_mapping(t_bytes32,t_struct(AddressSet)8661_storage)", + "src": "contracts/mainnet/DepositBoxes/DepositBoxERC1155.sol:51" + } + ], + "types": { + "t_mapping(t_bytes32,t_mapping(t_address,t_bool))": { + "label": "mapping(bytes32 => mapping(address => bool))" + }, + "t_bytes32": { + "label": "bytes32" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)" + }, + "t_address": { + "label": "address" + }, + "t_bool": { + "label": "bool" + }, + "t_mapping(t_bytes32,t_mapping(t_address,t_mapping(t_uint256,t_uint256)))": { + "label": "mapping(bytes32 => mapping(address => mapping(uint256 => uint256)))" + }, + "t_mapping(t_address,t_mapping(t_uint256,t_uint256))": { + "label": "mapping(address => mapping(uint256 => uint256))" + }, + "t_mapping(t_uint256,t_uint256)": { + "label": "mapping(uint256 => uint256)" + }, + "t_uint256": { + "label": "uint256" + }, + "t_mapping(t_bytes32,t_struct(AddressSet)8661_storage)": { + "label": "mapping(bytes32 => struct EnumerableSetUpgradeable.AddressSet)" + }, + "t_struct(AddressSet)8661_storage": { + "label": "struct EnumerableSetUpgradeable.AddressSet", + "members": [ + { + "label": "_inner", + "type": "t_struct(Set)8360_storage" + } + ] + }, + "t_struct(Set)8360_storage": { + "label": "struct EnumerableSetUpgradeable.Set", + "members": [ + { + "label": "_values", + "type": "t_array(t_bytes32)dyn_storage" + }, + { + "label": "_indexes", + "type": "t_mapping(t_bytes32,t_uint256)" + } + ] + }, + "t_array(t_bytes32)dyn_storage": { + "label": "bytes32[]" + }, + "t_mapping(t_bytes32,t_uint256)": { + "label": "mapping(bytes32 => uint256)" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]" + }, + "t_contract(ILinker)9807": { + "label": "contract ILinker" + }, + "t_mapping(t_bytes32,t_bool)": { + "label": "mapping(bytes32 => bool)" + }, + "t_contract(IMessageProxyForMainnet)9852": { + "label": "contract IMessageProxyForMainnet" + }, + "t_mapping(t_bytes32,t_address)": { + "label": "mapping(bytes32 => address)" + }, + "t_contract(IContractManager)10439": { + "label": "contract IContractManager" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]" + }, + "t_mapping(t_bytes32,t_struct(RoleData)179_storage)": { + "label": "mapping(bytes32 => struct AccessControlUpgradeable.RoleData)" + }, + "t_struct(RoleData)179_storage": { + "label": "struct AccessControlUpgradeable.RoleData", + "members": [ + { + "label": "members", + "type": "t_mapping(t_address,t_bool)" + }, + { + "label": "adminRole", + "type": "t_bytes32" + } + ] + }, + "t_uint8": { + "label": "uint8" + } + } + } + }, + "56782bd2021cf47b65b43729ea88fd9a9e3f1acb67ffd95f65ddcc13a1ae1dfd": { + "address": "0x858b1F991F248Dc150cE2B839d3d0d71597dBF68", + "txHash": "0xcefb865cfc9d422ab8aa3d89fa96dc040131c72445d4e9aa5afdd3e31fd92af7", + "layout": { + "storage": [ + { + "contract": "Initializable", + "label": "_initialized", + "type": "t_uint8", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:62" + }, + { + "contract": "Initializable", + "label": "_initializing", + "type": "t_bool", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:67" + }, + { + "contract": "ContextUpgradeable", + "label": "__gap", + "type": "t_array(t_uint256)50_storage", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" + }, + { + "contract": "ERC165Upgradeable", + "label": "__gap", + "type": "t_array(t_uint256)50_storage", + "src": "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol:41" + }, + { + "contract": "AccessControlUpgradeable", + "label": "_roles", + "type": "t_mapping(t_bytes32,t_struct(RoleData)179_storage)", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:61" + }, + { + "contract": "AccessControlUpgradeable", + "label": "__gap", + "type": "t_array(t_uint256)49_storage", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:259" + }, + { + "contract": "AccessControlEnumerableUpgradeable", + "label": "_roleMembers", + "type": "t_mapping(t_bytes32,t_struct(AddressSet)8661_storage)", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol:22" + }, + { + "contract": "AccessControlEnumerableUpgradeable", + "label": "__gap", + "type": "t_array(t_uint256)49_storage", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol:76" + }, + { + "contract": "SkaleManagerClient", + "label": "contractManagerOfSkaleManager", + "type": "t_contract(IContractManager)10439", + "src": "contracts/mainnet/SkaleManagerClient.sol:37" + }, + { + "contract": "Twin", + "label": "messageProxy", + "type": "t_contract(IMessageProxyForMainnet)9852", + "src": "contracts/mainnet/Twin.sol:38" + }, + { + "contract": "Twin", + "label": "schainLinks", + "type": "t_mapping(t_bytes32,t_address)", + "src": "contracts/mainnet/Twin.sol:39" + }, + { + "contract": "DepositBox", + "label": "linker", + "type": "t_contract(ILinker)9807", + "src": "contracts/mainnet/DepositBox.sol:36" + }, + { + "contract": "DepositBox", + "label": "_automaticDeploy", + "type": "t_mapping(t_bytes32,t_bool)", + "src": "contracts/mainnet/DepositBox.sol:39" + }, + { + "contract": "DepositBoxERC721", + "label": "_deprecatedSchainToERC721", + "type": "t_mapping(t_bytes32,t_mapping(t_address,t_bool))", + "src": "contracts/mainnet/DepositBoxes/DepositBoxERC721.sol:46" + }, + { + "contract": "DepositBoxERC721", + "label": "transferredAmount", + "type": "t_mapping(t_address,t_mapping(t_uint256,t_bytes32))", + "src": "contracts/mainnet/DepositBoxes/DepositBoxERC721.sol:47" + }, + { + "contract": "DepositBoxERC721", + "label": "_schainToERC721", + "type": "t_mapping(t_bytes32,t_struct(AddressSet)8661_storage)", + "src": "contracts/mainnet/DepositBoxes/DepositBoxERC721.sol:48" + } + ], + "types": { + "t_mapping(t_bytes32,t_mapping(t_address,t_bool))": { + "label": "mapping(bytes32 => mapping(address => bool))" + }, + "t_bytes32": { + "label": "bytes32" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)" + }, + "t_address": { + "label": "address" + }, + "t_bool": { + "label": "bool" + }, + "t_mapping(t_address,t_mapping(t_uint256,t_bytes32))": { + "label": "mapping(address => mapping(uint256 => bytes32))" + }, + "t_mapping(t_uint256,t_bytes32)": { + "label": "mapping(uint256 => bytes32)" + }, + "t_uint256": { + "label": "uint256" + }, + "t_mapping(t_bytes32,t_struct(AddressSet)8661_storage)": { + "label": "mapping(bytes32 => struct EnumerableSetUpgradeable.AddressSet)" + }, + "t_struct(AddressSet)8661_storage": { + "label": "struct EnumerableSetUpgradeable.AddressSet", + "members": [ + { + "label": "_inner", + "type": "t_struct(Set)8360_storage" + } + ] + }, + "t_struct(Set)8360_storage": { + "label": "struct EnumerableSetUpgradeable.Set", + "members": [ + { + "label": "_values", + "type": "t_array(t_bytes32)dyn_storage" + }, + { + "label": "_indexes", + "type": "t_mapping(t_bytes32,t_uint256)" + } + ] + }, + "t_array(t_bytes32)dyn_storage": { + "label": "bytes32[]" + }, + "t_mapping(t_bytes32,t_uint256)": { + "label": "mapping(bytes32 => uint256)" + }, + "t_contract(ILinker)9807": { + "label": "contract ILinker" + }, + "t_mapping(t_bytes32,t_bool)": { + "label": "mapping(bytes32 => bool)" + }, + "t_contract(IMessageProxyForMainnet)9852": { + "label": "contract IMessageProxyForMainnet" + }, + "t_mapping(t_bytes32,t_address)": { + "label": "mapping(bytes32 => address)" + }, + "t_contract(IContractManager)10439": { + "label": "contract IContractManager" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]" + }, + "t_mapping(t_bytes32,t_struct(RoleData)179_storage)": { + "label": "mapping(bytes32 => struct AccessControlUpgradeable.RoleData)" + }, + "t_struct(RoleData)179_storage": { + "label": "struct AccessControlUpgradeable.RoleData", + "members": [ + { + "label": "members", + "type": "t_mapping(t_address,t_bool)" + }, + { + "label": "adminRole", + "type": "t_bytes32" + } + ] + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]" + }, + "t_uint8": { + "label": "uint8" + } + } + } } } -} \ No newline at end of file +} diff --git a/proxy/DEPLOYED b/proxy/DEPLOYED index 10e7a5846..f15cad698 100644 --- a/proxy/DEPLOYED +++ b/proxy/DEPLOYED @@ -1 +1 @@ -1.3.4-stable.0 \ No newline at end of file +1.4.0-stable.0 \ No newline at end of file diff --git a/proxy/contracts/MessageProxy.sol b/proxy/contracts/MessageProxy.sol index bbcde9e2e..1a67e3133 100644 --- a/proxy/contracts/MessageProxy.sol +++ b/proxy/contracts/MessageProxy.sol @@ -58,8 +58,7 @@ abstract contract MessageProxy is AccessControlEnumerableUpgradeable, IMessagePr // schainHash => ConnectedChainInfo mapping(bytes32 => ConnectedChainInfo) public connectedChains; // schainHash => contract address => allowed - // solhint-disable-next-line private-vars-leading-underscore - mapping(bytes32 => mapping(address => bool)) internal deprecatedRegistryContracts; + mapping(bytes32 => mapping(address => bool)) private _deprecatedRegistryContracts; uint256 public gasLimit; @@ -142,13 +141,21 @@ abstract contract MessageProxy is AccessControlEnumerableUpgradeable, IMessagePr modifier onlyConstantSetter() { require(hasRole(CONSTANT_SETTER_ROLE, msg.sender), "Not enough permissions to set constant"); _; - } + } + + /** + * @dev Modifier to make a function callable only if caller is granted with {DEFAULT_ADMIN_ROLE}. + */ + modifier onlyOwner() { + require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), "DEFAULT_ADMIN_ROLE is required"); + _; + } /** * @dev Sets gasLimit to a new value. - * + * * Requirements: - * + * * - `msg.sender` must be granted CONSTANT_SETTER_ROLE. */ function setNewGasLimit(uint256 newGasLimit) external override onlyConstantSetter { @@ -172,9 +179,9 @@ abstract contract MessageProxy is AccessControlEnumerableUpgradeable, IMessagePr /** * @dev Allows `msg.sender` to register extra contract for all schains * for being able to transfer messages from custom contracts. - * + * * Requirements: - * + * * - `msg.sender` must be granted as EXTRA_CONTRACT_REGISTRAR_ROLE. * - Passed address should be contract. * - Extra contract must not be registered. @@ -189,9 +196,9 @@ abstract contract MessageProxy is AccessControlEnumerableUpgradeable, IMessagePr /** * @dev Allows `msg.sender` to remove extra contract for all schains. * Extra contract will no longer be able to send messages through MessageProxy. - * + * * Requirements: - * + * * - `msg.sender` must be granted as EXTRA_CONTRACT_REGISTRAR_ROLE. */ function removeExtraContractForAll(address extraContract) external override onlyExtraContractRegistrar { @@ -209,7 +216,7 @@ abstract contract MessageProxy is AccessControlEnumerableUpgradeable, IMessagePr /** * @dev Should return a range of contracts registered by schainHash. - * + * * Requirements: * range should be less or equal 10 contracts */ @@ -235,9 +242,9 @@ abstract contract MessageProxy is AccessControlEnumerableUpgradeable, IMessagePr /** * @dev Returns number of outgoing messages. - * + * * Requirements: - * + * * - Target schain must be initialized. */ function getOutgoingMessagesCounter(string calldata targetSchainName) @@ -263,9 +270,9 @@ abstract contract MessageProxy is AccessControlEnumerableUpgradeable, IMessagePr /** * @dev Returns number of incoming messages. - * + * * Requirements: - * + * * - Source schain must be initialized. */ function getIncomingMessagesCounter(string calldata fromSchainName) @@ -291,11 +298,11 @@ abstract contract MessageProxy is AccessControlEnumerableUpgradeable, IMessagePr /** * @dev Posts message from this contract to `targetChainHash` MessageProxy contract. * This is called by a smart contract to make a cross-chain call. - * + * * Emits an {OutgoingMessage} event. * * Requirements: - * + * * - Target chain must be initialized. * - Target chain must be registered as external contract. */ @@ -310,7 +317,7 @@ abstract contract MessageProxy is AccessControlEnumerableUpgradeable, IMessagePr { require(connectedChains[targetChainHash].inited, "Destination chain is not initialized"); _authorizeOutgoingMessageSender(targetChainHash); - + uint outgoingMessageCounter = connectedChains[targetChainHash].outgoingMessageCounter; emit OutgoingMessage( targetChainHash, @@ -329,9 +336,9 @@ abstract contract MessageProxy is AccessControlEnumerableUpgradeable, IMessagePr /** * @dev Allows CHAIN_CONNECTOR_ROLE to remove connected chain from this contract. - * + * * Requirements: - * + * * - `msg.sender` must be granted CHAIN_CONNECTOR_ROLE. * - `schainName` must be initialized. */ @@ -339,7 +346,7 @@ abstract contract MessageProxy is AccessControlEnumerableUpgradeable, IMessagePr bytes32 schainHash = keccak256(abi.encodePacked(schainName)); require(connectedChains[schainHash].inited, "Chain is not initialized"); delete connectedChains[schainHash]; - } + } /** * @dev Checks whether chain is currently connected. @@ -373,9 +380,9 @@ abstract contract MessageProxy is AccessControlEnumerableUpgradeable, IMessagePr /** * @dev Allows MessageProxy to register extra contract for being able to transfer messages from custom contracts. - * + * * Requirements: - * + * * - Extra contract address must be contract. * - Extra contract must not be registered. * - Extra contract must not be registered for all chains. @@ -385,14 +392,14 @@ abstract contract MessageProxy is AccessControlEnumerableUpgradeable, IMessagePr address extraContract ) internal - { + { require(extraContract.isContract(), "Given address is not a contract"); require(!_getRegistryContracts()[chainHash].contains(extraContract), "Extra contract is already registered"); require( !_getRegistryContracts()[bytes32(0)].contains(extraContract), "Extra contract is already registered for all chains" ); - + _getRegistryContracts()[chainHash].add(extraContract); emit ExtraContractRegistered(chainHash, extraContract); } @@ -400,9 +407,9 @@ abstract contract MessageProxy is AccessControlEnumerableUpgradeable, IMessagePr /** * @dev Allows MessageProxy to remove extra contract, * thus `extraContract` will no longer be available to transfer messages from mainnet to schain. - * + * * Requirements: - * + * * - Extra contract must be registered. */ function _removeExtraContract( @@ -418,9 +425,9 @@ abstract contract MessageProxy is AccessControlEnumerableUpgradeable, IMessagePr /** * @dev Allows MessageProxy to connect schain with MessageProxyOnMainnet for transferring messages. - * + * * Requirements: - * + * * - `msg.sender` must be granted CHAIN_CONNECTOR_ROLE. * - SKALE chain must not be connected. */ @@ -521,7 +528,7 @@ abstract contract MessageProxy is AccessControlEnumerableUpgradeable, IMessagePr require( isContractRegistered(bytes32(0), msg.sender) || isContractRegistered(targetChainHash, msg.sender), "Sender contract is not registered" - ); + ); } /** @@ -568,6 +575,6 @@ abstract contract MessageProxy is AccessControlEnumerableUpgradeable, IMessagePr for(uint i = 0; i < slicedEnd; i++){ sliced[i] = text[i]; } - return sliced; + return sliced; } } diff --git a/proxy/contracts/mainnet/DepositBoxes/DepositBoxERC1155.sol b/proxy/contracts/mainnet/DepositBoxes/DepositBoxERC1155.sol index 2b5a2f49d..c91d98548 100644 --- a/proxy/contracts/mainnet/DepositBoxes/DepositBoxERC1155.sol +++ b/proxy/contracts/mainnet/DepositBoxes/DepositBoxERC1155.sol @@ -77,30 +77,8 @@ contract DepositBoxERC1155 is DepositBox, ERC1155ReceiverUpgradeable, IDepositBo ) external override - rightTransaction(schainName, msg.sender) - whenNotKilled(keccak256(abi.encodePacked(schainName))) { - bytes32 schainHash = keccak256(abi.encodePacked(schainName)); - address contractReceiver = schainLinks[schainHash]; - require(contractReceiver != address(0), "Unconnected chain"); - require( - IERC1155Upgradeable(erc1155OnMainnet).isApprovedForAll(msg.sender, address(this)), - "DepositBox was not approved for ERC1155 token" - ); - bytes memory data = _receiveERC1155( - schainName, - erc1155OnMainnet, - msg.sender, - id, - amount - ); - _saveTransferredAmount(schainHash, erc1155OnMainnet, _asSingletonArray(id), _asSingletonArray(amount)); - IERC1155Upgradeable(erc1155OnMainnet).safeTransferFrom(msg.sender, address(this), id, amount, ""); - messageProxy.postOutgoingMessage( - schainHash, - contractReceiver, - data - ); + depositERC1155Direct(schainName, erc1155OnMainnet, id, amount, msg.sender); } /** @@ -119,30 +97,8 @@ contract DepositBoxERC1155 is DepositBox, ERC1155ReceiverUpgradeable, IDepositBo ) external override - rightTransaction(schainName, msg.sender) - whenNotKilled(keccak256(abi.encodePacked(schainName))) { - bytes32 schainHash = keccak256(abi.encodePacked(schainName)); - address contractReceiver = schainLinks[schainHash]; - require(contractReceiver != address(0), "Unconnected chain"); - require( - IERC1155Upgradeable(erc1155OnMainnet).isApprovedForAll(msg.sender, address(this)), - "DepositBox was not approved for ERC1155 token Batch" - ); - bytes memory data = _receiveERC1155Batch( - schainName, - erc1155OnMainnet, - msg.sender, - ids, - amounts - ); - _saveTransferredAmount(schainHash, erc1155OnMainnet, ids, amounts); - IERC1155Upgradeable(erc1155OnMainnet).safeBatchTransferFrom(msg.sender, address(this), ids, amounts, ""); - messageProxy.postOutgoingMessage( - schainHash, - contractReceiver, - data - ); + depositERC1155BatchDirect(schainName, erc1155OnMainnet, ids, amounts, msg.sender); } /** @@ -389,6 +345,92 @@ contract DepositBoxERC1155 is DepositBox, ERC1155ReceiverUpgradeable, IDepositBo __ERC1155Receiver_init(); } + /** + * @dev Allows `msg.sender` to send ERC1155 token from mainnet to schain to specified receiver. + * + * Requirements: + * + * - Receiver contract should be defined. + * - `msg.sender` should approve their tokens for DepositBoxERC1155 address. + */ + function depositERC1155Direct( + string calldata schainName, + address erc1155OnMainnet, + uint256 id, + uint256 amount, + address receiver + ) + public + override + rightTransaction(schainName, receiver) + whenNotKilled(keccak256(abi.encodePacked(schainName))) + { + bytes32 schainHash = keccak256(abi.encodePacked(schainName)); + address contractReceiver = schainLinks[schainHash]; + require(contractReceiver != address(0), "Unconnected chain"); + require( + IERC1155Upgradeable(erc1155OnMainnet).isApprovedForAll(msg.sender, address(this)), + "DepositBox was not approved for ERC1155 token" + ); + bytes memory data = _receiveERC1155( + schainName, + erc1155OnMainnet, + receiver, + id, + amount + ); + _saveTransferredAmount(schainHash, erc1155OnMainnet, _asSingletonArray(id), _asSingletonArray(amount)); + IERC1155Upgradeable(erc1155OnMainnet).safeTransferFrom(msg.sender, address(this), id, amount, ""); + messageProxy.postOutgoingMessage( + schainHash, + contractReceiver, + data + ); + } + + /** + * @dev Allows `msg.sender` to send batch of ERC1155 tokens from mainnet to schain to specified receiver. + * + * Requirements: + * + * - Receiver contract should be defined. + * - `msg.sender` should approve their tokens for DepositBoxERC1155 address. + */ + function depositERC1155BatchDirect( + string calldata schainName, + address erc1155OnMainnet, + uint256[] calldata ids, + uint256[] calldata amounts, + address receiver + ) + public + override + rightTransaction(schainName, receiver) + whenNotKilled(keccak256(abi.encodePacked(schainName))) + { + bytes32 schainHash = keccak256(abi.encodePacked(schainName)); + address contractReceiver = schainLinks[schainHash]; + require(contractReceiver != address(0), "Unconnected chain"); + require( + IERC1155Upgradeable(erc1155OnMainnet).isApprovedForAll(msg.sender, address(this)), + "DepositBox was not approved for ERC1155 token Batch" + ); + bytes memory data = _receiveERC1155Batch( + schainName, + erc1155OnMainnet, + receiver, + ids, + amounts + ); + _saveTransferredAmount(schainHash, erc1155OnMainnet, ids, amounts); + IERC1155Upgradeable(erc1155OnMainnet).safeBatchTransferFrom(msg.sender, address(this), ids, amounts, ""); + messageProxy.postOutgoingMessage( + schainHash, + contractReceiver, + data + ); + } + /** * @dev Checks whether contract supports such interface (first 4 bytes of method name and its params). */ diff --git a/proxy/contracts/mainnet/DepositBoxes/DepositBoxERC20.sol b/proxy/contracts/mainnet/DepositBoxes/DepositBoxERC20.sol index 4f25abadf..dea7b077e 100644 --- a/proxy/contracts/mainnet/DepositBoxes/DepositBoxERC20.sol +++ b/proxy/contracts/mainnet/DepositBoxes/DepositBoxERC20.sol @@ -161,29 +161,8 @@ contract DepositBoxERC20 is DepositBox, IDepositBoxERC20 { ) external override - rightTransaction(schainName, msg.sender) - whenNotKilled(_schainHash(schainName)) { - bytes32 schainHash = _schainHash(schainName); - address contractReceiver = schainLinks[schainHash]; - require(contractReceiver != address(0), "Unconnected chain"); - require( - IERC20MetadataUpgradeable(erc20OnMainnet).allowance(msg.sender, address(this)) >= amount, - "DepositBox was not approved for ERC20 token" - ); - bytes memory data = _receiveERC20( - schainName, - erc20OnMainnet, - msg.sender, - amount - ); - _saveTransferredAmount(schainHash, erc20OnMainnet, amount); - IERC20MetadataUpgradeable(erc20OnMainnet).safeTransferFrom(msg.sender, address(this), amount); - messageProxy.postOutgoingMessage( - schainHash, - contractReceiver, - data - ); + depositERC20Direct(schainName, erc20OnMainnet, amount, msg.sender); } /** @@ -685,6 +664,50 @@ contract DepositBoxERC20 is DepositBox, IDepositBoxERC20 { DepositBox.initialize(contractManagerOfSkaleManagerValue, linkerValue, messageProxyValue); } + /** + * @dev Allows `msg.sender` to send ERC20 token from mainnet to schain to specified receiver. + * + * Requirements: + * + * - Schain name must not be `Mainnet`. + * - Receiver account on schain cannot be null. + * - Schain that receives tokens should not be killed. + * - Receiver contract should be defined. + * - `msg.sender` should approve their tokens for DepositBoxERC20 address. + */ + function depositERC20Direct( + string calldata schainName, + address erc20OnMainnet, + uint256 amount, + address receiver + ) + public + override + rightTransaction(schainName, receiver) + whenNotKilled(_schainHash(schainName)) + { + bytes32 schainHash = _schainHash(schainName); + address contractReceiver = schainLinks[schainHash]; + require(contractReceiver != address(0), "Unconnected chain"); + require( + IERC20Upgradeable(erc20OnMainnet).allowance(msg.sender, address(this)) >= amount, + "DepositBox was not approved for ERC20 token" + ); + bytes memory data = _receiveERC20( + schainName, + erc20OnMainnet, + receiver, + amount + ); + _saveTransferredAmount(schainHash, erc20OnMainnet, amount); + IERC20MetadataUpgradeable(erc20OnMainnet).safeTransferFrom(msg.sender, address(this), amount); + messageProxy.postOutgoingMessage( + schainHash, + contractReceiver, + data + ); + } + /** * @dev Check if the receiver is in the delay whitelist */ diff --git a/proxy/contracts/mainnet/DepositBoxes/DepositBoxERC721.sol b/proxy/contracts/mainnet/DepositBoxes/DepositBoxERC721.sol index b6674f9ad..163e3af99 100644 --- a/proxy/contracts/mainnet/DepositBoxes/DepositBoxERC721.sol +++ b/proxy/contracts/mainnet/DepositBoxes/DepositBoxERC721.sol @@ -73,29 +73,8 @@ contract DepositBoxERC721 is DepositBox, IDepositBoxERC721 { ) external override - rightTransaction(schainName, msg.sender) - whenNotKilled(keccak256(abi.encodePacked(schainName))) { - bytes32 schainHash = keccak256(abi.encodePacked(schainName)); - address contractReceiver = schainLinks[schainHash]; - require(contractReceiver != address(0), "Unconnected chain"); - require( - IERC721Upgradeable(erc721OnMainnet).getApproved(tokenId) == address(this), - "DepositBox was not approved for ERC721 token" - ); - bytes memory data = _receiveERC721( - schainName, - erc721OnMainnet, - msg.sender, - tokenId - ); - _saveTransferredAmount(schainHash, erc721OnMainnet, tokenId); - IERC721Upgradeable(erc721OnMainnet).transferFrom(msg.sender, address(this), tokenId); - messageProxy.postOutgoingMessage( - schainHash, - contractReceiver, - data - ); + depositERC721Direct(schainName, erc721OnMainnet, tokenId, msg.sender); } /** @@ -238,6 +217,47 @@ contract DepositBoxERC721 is DepositBox, IDepositBoxERC721 { DepositBox.initialize(contractManagerOfSkaleManagerValue, linkerValue, messageProxyValue); } + /** + * @dev Allows `msg.sender` to send ERC721 token from mainnet to schain to specified receiver. + * + * Requirements: + * + * - Receiver contract should be defined. + * - `msg.sender` should approve their token for DepositBoxERC721 address. + */ + function depositERC721Direct( + string calldata schainName, + address erc721OnMainnet, + uint256 tokenId, + address receiver + ) + public + override + rightTransaction(schainName, receiver) + whenNotKilled(keccak256(abi.encodePacked(schainName))) + { + bytes32 schainHash = keccak256(abi.encodePacked(schainName)); + address contractReceiver = schainLinks[schainHash]; + require(contractReceiver != address(0), "Unconnected chain"); + require( + IERC721Upgradeable(erc721OnMainnet).getApproved(tokenId) == address(this), + "DepositBox was not approved for ERC721 token" + ); + bytes memory data = _receiveERC721( + schainName, + erc721OnMainnet, + receiver, + tokenId + ); + _saveTransferredAmount(schainHash, erc721OnMainnet, tokenId); + IERC721Upgradeable(erc721OnMainnet).transferFrom(msg.sender, address(this), tokenId); + messageProxy.postOutgoingMessage( + schainHash, + contractReceiver, + data + ); + } + /** * @dev Should return true if token was added by Schain owner or * automatically added after sending to schain if whitelist was turned off. diff --git a/proxy/contracts/mainnet/DepositBoxes/DepositBoxEth.sol b/proxy/contracts/mainnet/DepositBoxes/DepositBoxEth.sol index 9fa310437..6d0b34362 100644 --- a/proxy/contracts/mainnet/DepositBoxes/DepositBoxEth.sol +++ b/proxy/contracts/mainnet/DepositBoxes/DepositBoxEth.sol @@ -61,18 +61,8 @@ contract DepositBoxEth is DepositBox, IDepositBoxEth { external payable override - rightTransaction(schainName, msg.sender) - whenNotKilled(keccak256(abi.encodePacked(schainName))) { - bytes32 schainHash = keccak256(abi.encodePacked(schainName)); - address contractReceiver = schainLinks[schainHash]; - require(contractReceiver != address(0), "Unconnected chain"); - _saveTransferredAmount(schainHash, msg.value); - messageProxy.postOutgoingMessage( - schainHash, - contractReceiver, - Messages.encodeTransferEthMessage(msg.sender, msg.value) - ); + depositDirect(schainName, msg.sender); } /** @@ -223,6 +213,33 @@ contract DepositBoxEth is DepositBox, IDepositBoxEth { DepositBox.initialize(contractManagerOfSkaleManagerValue, linkerValue, messageProxyValue); } + /** + * @dev Allows `msg.sender` to send ETH from mainnet to schain to specified receiver. + * + * Requirements: + * + * - Schain name must not be `Mainnet`. + * - Receiver contract should be added as twin contract on schain. + * - Schain that receives tokens should not be killed. + */ + function depositDirect(string memory schainName, address receiver) + public + payable + override + rightTransaction(schainName, receiver) + whenNotKilled(keccak256(abi.encodePacked(schainName))) + { + bytes32 schainHash = keccak256(abi.encodePacked(schainName)); + address contractReceiver = schainLinks[schainHash]; + require(contractReceiver != address(0), "Unconnected chain"); + _saveTransferredAmount(schainHash, msg.value); + messageProxy.postOutgoingMessage( + schainHash, + contractReceiver, + Messages.encodeTransferEthMessage(receiver, msg.value) + ); + } + /** * @dev Saves amount of ETH that was transferred to schain. */ diff --git a/proxy/contracts/mainnet/MessageProxyForMainnet.sol b/proxy/contracts/mainnet/MessageProxyForMainnet.sol index e2c9ebe84..8216a1c60 100644 --- a/proxy/contracts/mainnet/MessageProxyForMainnet.sol +++ b/proxy/contracts/mainnet/MessageProxyForMainnet.sol @@ -174,8 +174,7 @@ contract MessageProxyForMainnet is SkaleManagerClient, MessageProxy, IMessagePro * - `msg.sender` must be granted as DEFAULT_ADMIN_ROLE. * - Address of CommunityPool contract must not be null. */ - function setCommunityPool(ICommunityPool newCommunityPoolAddress) external override { - require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), "Not authorized caller"); + function setCommunityPool(ICommunityPool newCommunityPoolAddress) external override onlyOwner { require(address(newCommunityPoolAddress) != address(0), "CommunityPool address has to be set"); communityPool = newCommunityPoolAddress; } @@ -358,8 +357,7 @@ contract MessageProxyForMainnet is SkaleManagerClient, MessageProxy, IMessagePro * * - `msg.sender` must be granted DEFAULT_ADMIN_ROLE. */ - function setVersion(string calldata newVersion) external override { - require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), "DEFAULT_ADMIN_ROLE is required"); + function setVersion(string calldata newVersion) external override onlyOwner { emit VersionUpdated(version, newVersion); version = newVersion; } diff --git a/proxy/contracts/schain/CommunityLocker.sol b/proxy/contracts/schain/CommunityLocker.sol index 52683d27d..61a74af3b 100644 --- a/proxy/contracts/schain/CommunityLocker.sol +++ b/proxy/contracts/schain/CommunityLocker.sol @@ -206,7 +206,7 @@ contract CommunityLocker is ICommunityLockerInitializer, AccessControlEnumerable override { require( - tokenManagerLinker.hasTokenManager(ITokenManager(msg.sender)), + tokenManagerLinker.hasTokenManager(msg.sender), "Sender is not registered token manager" ); if (chainHash == MAINNET_HASH) { diff --git a/proxy/contracts/schain/DefaultAddresses.sol b/proxy/contracts/schain/DefaultAddresses.sol new file mode 100644 index 000000000..e467be99d --- /dev/null +++ b/proxy/contracts/schain/DefaultAddresses.sol @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: AGPL-3.0-only + +/** + * DefaultAddresses.sol - SKALE Interchain Messaging Agent + * Copyright (C) 2022-Present SKALE Labs + * @author Dmytro Stebaiev + * + * SKALE IMA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SKALE IMA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with SKALE IMA. If not, see . + */ + + pragma solidity 0.8.16; + +library DefaultAddresses { + // 17 0x00 bytes + address public constant ETHERBASE = address(0xd2bA3e << (17 * 8)); + // 16 0x00 bytes + address public constant TOKEN_MANAGER_LINKER = address(0xD2aAA008 << (16 * 8)); +} \ No newline at end of file diff --git a/proxy/contracts/schain/MessageProxyForSchain.sol b/proxy/contracts/schain/MessageProxyForSchain.sol index e96bd90e5..625ccf1c4 100644 --- a/proxy/contracts/schain/MessageProxyForSchain.sol +++ b/proxy/contracts/schain/MessageProxyForSchain.sol @@ -27,15 +27,17 @@ import "@skalenetwork/etherbase-interfaces/IEtherbaseUpgradeable.sol"; import "../MessageProxy.sol"; import "./bls/SkaleVerifier.sol"; +import "./DefaultAddresses.sol"; +import "./TokenManagerLinker.sol"; /** * @title MessageProxyForSchain * @dev Entry point for messages that come from mainnet or other SKALE chains * and contract that emits messages for mainnet or other SKALE chains. - * + * * Messages are submitted by IMA-agent and secured with threshold signature. - * + * * IMA-agent monitors events of {MessageProxyForSchain} and sends messages to other chains. * NOTE: 16 Agents @@ -55,7 +57,7 @@ contract MessageProxyForSchain is MessageProxy, IMessageProxyForSchain { using EnumerableSetUpgradeable for EnumerableSetUpgradeable.AddressSet; IEtherbaseUpgradeable public constant ETHERBASE = IEtherbaseUpgradeable( - payable(0xd2bA3e0000000000000000000000000000000000) + payable(DefaultAddresses.ETHERBASE) ); uint public constant MINIMUM_BALANCE = 1 ether; @@ -99,6 +101,20 @@ contract MessageProxyForSchain is MessageProxy, IMessageProxyForSchain { string public version; bool public override messageInProgress; + /** + * @dev if receiver has no sFuil it's balance is topupped from etherbase for the value + * if the value is 0 MINIMUM_BALANCE is used + */ + uint256 public minimumReceiverBalance; + + /** + * @dev the event is emitted when value of receiver's minimum balance is changed + */ + event MinimumReceiverBalanceChanged ( + uint256 oldValue, + uint256 newValue + ); + /** * @dev Reentrancy guard for postIncomingMessages. */ @@ -111,9 +127,9 @@ contract MessageProxyForSchain is MessageProxy, IMessageProxyForSchain { /** * @dev Allows MessageProxy to register extra contract for being able to transfer messages from custom contracts. - * + * * Requirements: - * + * * - Function caller has to be granted with {EXTRA_CONTRACT_REGISTRAR_ROLE}. * - Destination chain hash cannot be equal to itself */ @@ -133,9 +149,9 @@ contract MessageProxyForSchain is MessageProxy, IMessageProxyForSchain { /** * @dev Allows MessageProxy to remove extra contract, * thus `extraContract` will no longer be available to transfer messages from chain to chain. - * + * * Requirements: - * + * * - Function caller has to be granted with {EXTRA_CONTRACT_REGISTRAR_ROLE}. * - Destination chain hash cannot be equal to itself */ @@ -156,9 +172,9 @@ contract MessageProxyForSchain is MessageProxy, IMessageProxyForSchain { * @dev Link external chain. * * NOTE: Mainnet is linked automatically. - * + * * Requirements: - * + * * - Function caller has to be granted with {CHAIN_CONNECTOR_ROLE}. * - Target chain must be different from the current. */ @@ -166,14 +182,14 @@ contract MessageProxyForSchain is MessageProxy, IMessageProxyForSchain { bytes32 chainHash = keccak256(abi.encodePacked(chainName)); require(chainHash != schainHash, "Schain cannot connect itself"); _addConnectedChain(chainHash); - } + } /** * @dev Entry point for incoming messages. * This function is called by IMA-agent to deliver incoming messages from external chains. - * + * * Requirements: - * + * * - Origin chain has to be registered. * - Amount of messages must be no more than {MESSAGES_LENGTH}. * - Messages batch has to be signed with threshold signature. @@ -184,7 +200,7 @@ contract MessageProxyForSchain is MessageProxy, IMessageProxyForSchain { string calldata fromChainName, uint256 startingCounter, Message[] calldata messages, - Signature calldata signature + Signature calldata signature ) external override(IMessageProxy, MessageProxy) @@ -203,22 +219,42 @@ contract MessageProxyForSchain is MessageProxy, IMessageProxyForSchain { for (uint256 i = 0; i < messages.length; i++) { _callReceiverContract(fromChainHash, messages[i], startingCounter + 1); } - _topUpBalance(); + _topUpSenderBalance(); } /** * @dev Sets new version of contracts on schain - * + * * Requirements: - * + * * - `msg.sender` must be granted DEFAULT_ADMIN_ROLE. */ - function setVersion(string calldata newVersion) external override { - require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender), "DEFAULT_ADMIN_ROLE is required"); + function setVersion(string calldata newVersion) external override onlyOwner { emit VersionUpdated(version, newVersion); version = newVersion; } + /** + * @dev Sets a minimum balance of a receiver. + * If the balance is lower IMA tries to send sFuel to top up it. + */ + function setMinimumReceiverBalance(uint256 balance) external override onlyConstantSetter { + emit MinimumReceiverBalanceChanged(minimumReceiverBalance, balance); + minimumReceiverBalance = balance; + } + + /** + * @dev Sends sFuel to the `receiver` address to satisfy a minimum balance + */ + function topUpReceiverBalance(address payable receiver) external override { + require(isContractRegistered(bytes32(0), msg.sender), "Sender is not registered"); + uint256 balance = receiver.balance; + uint256 threshold = minimumReceiverBalance; + if (balance < threshold) { + _transferFromEtherbase(receiver, threshold - balance); + } + } + /** * @dev Verify if the message metadata is valid. */ @@ -274,9 +310,9 @@ contract MessageProxyForSchain is MessageProxy, IMessageProxyForSchain { /** * @dev Unlink external SKALE chain. - * + * * Requirements: - * + * * - Function caller has to be granted with {CHAIN_CONNECTOR_ROLE}. * - Target chain must be different from Mainnet. */ @@ -295,9 +331,9 @@ contract MessageProxyForSchain is MessageProxy, IMessageProxyForSchain { /** * @dev This function is called by a smart contract * that wants to make a cross-chain call. - * + * * Requirements: - * + * * - Destination chain has to be registered. * - Sender contract has to be registered. */ @@ -373,20 +409,27 @@ contract MessageProxyForSchain is MessageProxy, IMessageProxyForSchain { } /** - * @dev Move skETH from Etherbase if the balance is too low + * @dev Move SFuel from Etherbase if the sender balance is too low */ - function _topUpBalance() private { + function _topUpSenderBalance() private { uint balance = msg.sender.balance + gasleft() * tx.gasprice; + if (balance < MINIMUM_BALANCE) { + _transferFromEtherbase(payable(msg.sender), MINIMUM_BALANCE - balance); + } + } + + /** + * @dev Move SFuel from Etherbase to `target` address + */ + function _transferFromEtherbase(address payable target, uint256 value) private { IEtherbaseUpgradeable etherbase = _getEtherbase(); if (address(etherbase).isContract() - && etherbase.hasRole(etherbase.ETHER_MANAGER_ROLE(), address(this)) - && balance < MINIMUM_BALANCE + && etherbase.hasRole(etherbase.ETHER_MANAGER_ROLE(), address(this)) ) { - uint missingAmount = MINIMUM_BALANCE - balance; - if (missingAmount < address(etherbase).balance) { - etherbase.partiallyRetrieve(payable(msg.sender), missingAmount); + if (value < address(etherbase).balance) { + etherbase.partiallyRetrieve(target, value); } else { - etherbase.retrieve(payable(msg.sender)); + etherbase.retrieve(target); } } } @@ -403,5 +446,5 @@ contract MessageProxyForSchain is MessageProxy, IMessageProxyForSchain { message.data ); return keccak256(data); - } + } } diff --git a/proxy/contracts/schain/TokenManagerLinker.sol b/proxy/contracts/schain/TokenManagerLinker.sol index ac9501c2a..048dae3e2 100644 --- a/proxy/contracts/schain/TokenManagerLinker.sol +++ b/proxy/contracts/schain/TokenManagerLinker.sol @@ -172,11 +172,12 @@ contract TokenManagerLinker is ITokenManagerLinker, AccessControlEnumerableUpgra /** * @dev Check if {tokenManager} is registered in IMA. */ - function hasTokenManager(ITokenManager tokenManager) external view override returns (bool) { + function hasTokenManager(address tokenManager) external view override returns (bool) { + // TODO: optimize algorithm to save gas uint index; uint length = tokenManagers.length; for (index = 0; index < length; index++) { - if (tokenManagers[index] == tokenManager) { + if (address(tokenManagers[index]) == tokenManager) { return true; } } diff --git a/proxy/contracts/schain/TokenManagers/TokenManagerERC1155.sol b/proxy/contracts/schain/TokenManagers/TokenManagerERC1155.sol index ae7e62ae8..05aaab524 100644 --- a/proxy/contracts/schain/TokenManagers/TokenManagerERC1155.sol +++ b/proxy/contracts/schain/TokenManagers/TokenManagerERC1155.sol @@ -357,6 +357,7 @@ contract TokenManagerERC1155 is _asSingletonArray(id), _asSingletonArray(amount) ); + messageProxy.topUpReceiverBalance(payable(receiver)); return receiver; } @@ -407,6 +408,7 @@ contract TokenManagerERC1155 is contractOnSchain.mintBatch(receiver, ids, amounts, ""); } emit ERC1155TokenReceived(fromChainHash, token, address(contractOnSchain), ids, amounts); + messageProxy.topUpReceiverBalance(payable(receiver)); return receiver; } diff --git a/proxy/contracts/schain/TokenManagers/TokenManagerERC20.sol b/proxy/contracts/schain/TokenManagers/TokenManagerERC20.sol index a502b90fd..55c0cbbd0 100644 --- a/proxy/contracts/schain/TokenManagers/TokenManagerERC20.sol +++ b/proxy/contracts/schain/TokenManagers/TokenManagerERC20.sol @@ -254,6 +254,7 @@ contract TokenManagerERC20 is TokenManager, ITokenManagerERC20 { ); } emit ERC20TokenReceived(fromChainHash, token, address(contractOnSchain), amount); + messageProxy.topUpReceiverBalance(payable(receiver)); return receiver; } diff --git a/proxy/contracts/schain/TokenManagers/TokenManagerERC721.sol b/proxy/contracts/schain/TokenManagers/TokenManagerERC721.sol index 34c6fe4ee..0315bfc6d 100644 --- a/proxy/contracts/schain/TokenManagers/TokenManagerERC721.sol +++ b/proxy/contracts/schain/TokenManagers/TokenManagerERC721.sol @@ -246,6 +246,7 @@ contract TokenManagerERC721 is TokenManager, ITokenManagerERC721 { contractOnSchain.mint(receiver, tokenId); } emit ERC721TokenReceived(fromChainHash, token, address(contractOnSchain), tokenId); + messageProxy.topUpReceiverBalance(payable(receiver)); return receiver; } diff --git a/proxy/contracts/schain/TokenManagers/TokenManagerERC721WithMetadata.sol b/proxy/contracts/schain/TokenManagers/TokenManagerERC721WithMetadata.sol index 51807eeef..076322482 100644 --- a/proxy/contracts/schain/TokenManagers/TokenManagerERC721WithMetadata.sol +++ b/proxy/contracts/schain/TokenManagers/TokenManagerERC721WithMetadata.sol @@ -120,6 +120,7 @@ contract TokenManagerERC721WithMetadata is TokenManagerERC721 { contractOnSchain.setTokenURI(tokenId, tokenURI); } emit ERC721TokenReceived(fromChainHash, token, address(contractOnSchain), tokenId); + messageProxy.topUpReceiverBalance(payable(receiver)); return receiver; } diff --git a/proxy/contracts/schain/TokenManagers/TokenManagerEth.sol b/proxy/contracts/schain/TokenManagers/TokenManagerEth.sol index 56fe9565e..2a339bd2c 100644 --- a/proxy/contracts/schain/TokenManagers/TokenManagerEth.sol +++ b/proxy/contracts/schain/TokenManagers/TokenManagerEth.sol @@ -81,6 +81,7 @@ contract TokenManagerEth is TokenManager, ITokenManagerEth { address receiver = decodedMessage.receiver; require(receiver != address(0), "Incorrect receiver"); ethErc20.mint(receiver, decodedMessage.amount); + messageProxy.topUpReceiverBalance(payable(receiver)); } /** diff --git a/proxy/contracts/test/MessageProxyForSchainWithoutSignature.sol b/proxy/contracts/test/MessageProxyForSchainWithoutSignature.sol index 47e63829b..c287cf1d0 100644 --- a/proxy/contracts/test/MessageProxyForSchainWithoutSignature.sol +++ b/proxy/contracts/test/MessageProxyForSchainWithoutSignature.sol @@ -25,7 +25,8 @@ import "./MessageProxyForSchainTester.sol"; contract MessageProxyForSchainWithoutSignature is MessageProxyForSchainTester { - constructor(string memory schainName) MessageProxyForSchainTester(IKeyStorage(address(0)), schainName) + constructor(string memory schainName) + MessageProxyForSchainTester(IKeyStorage(address(0)), schainName) // solhint-disable-next-line no-empty-blocks {} diff --git a/proxy/migrations/deployMainnet.ts b/proxy/migrations/deployMainnet.ts index 46238ae28..7bd13f733 100644 --- a/proxy/migrations/deployMainnet.ts +++ b/proxy/migrations/deployMainnet.ts @@ -24,13 +24,10 @@ */ import { promises as fs } from 'fs'; import { Interface } from "ethers/lib/utils"; -import { ethers, upgrades, artifacts, web3 } from "hardhat"; +import { ethers, upgrades, web3 } from "hardhat"; import { MessageProxyForMainnet, Linker } from "../typechain"; -import { deployLibraries, getLinkedContractFactory } from "./tools/factory"; -import { getAbi } from './tools/abi'; -import { verify, verifyProxy } from './tools/verification'; -import { Manifest, hashBytecode } from "@openzeppelin/upgrades-core"; -import { getVersion } from './tools/version'; +import { getAbi, getContractFactory, verifyProxy, getVersion } from '@skalenetwork/upgrade-tools'; +import { Manifest } from "@openzeppelin/upgrades-core"; export function getContractKeyInAbiFile(contract: string) { if (contract === "MessageProxyForMainnet") { @@ -43,35 +40,6 @@ export async function getManifestFile(): Promise { return (await Manifest.forNetwork(ethers.provider)).file;; } -export async function getContractFactory(contract: string) { - const { linkReferences } = await artifacts.readArtifact(contract); - if (!Object.keys(linkReferences).length) - return await ethers.getContractFactory(contract); - - const libraryNames = []; - for (const key of Object.keys(linkReferences)) { - const libraryName = Object.keys(linkReferences[key])[0]; - libraryNames.push(libraryName); - } - - const libraries = await deployLibraries(libraryNames); - const libraryArtifacts: {[key: string]: any} = {}; - for (const libraryName of Object.keys(libraries)) { - const { bytecode } = await artifacts.readArtifact(libraryName); - libraryArtifacts[libraryName] = {"address": libraries[libraryName], "bytecodeHash": hashBytecode(bytecode)}; - } - let manifest: any; - try { - manifest = JSON.parse(await fs.readFile(await getManifestFile(), "utf-8")); - Object.assign(libraryArtifacts, manifest.libraries); - } finally { - Object.assign(manifest, {libraries: libraryArtifacts}); - await fs.writeFile(await getManifestFile(), JSON.stringify(manifest, null, 4)); - } - return await getLinkedContractFactory(contract, libraries); -} - - export function getContractManager() { const defaultFilePath = "../data/skaleManagerComponents.json"; const jsonData = require(defaultFilePath); @@ -223,12 +191,19 @@ async function main() { const outputObject: {[k: string]: any} = {}; for (const contract of contracts) { const contractKey = getContractKeyInAbiFile(contract); - outputObject[contractKey + "_address"] = deployed.get(contract)?.address; - outputObject[contractKey + "_abi"] = getAbi(deployed.get(contract)?.interface); + const deployedContract = deployed.get(contract); + if (deployedContract === undefined) { + throw Error(`Contract ${contract} was not found`); + } + outputObject[contractKey + "_address"] = deployedContract.address; + outputObject[contractKey + "_abi"] = getAbi(deployedContract.interface); } - - outputObject[getContractKeyInAbiFile("DepositBoxERC721WithMetadata") + "_address"] = deployed.get("DepositBoxERC721WithMetadata")?.address; - outputObject[getContractKeyInAbiFile("DepositBoxERC721WithMetadata") + "_abi"] = getAbi(deployed.get("DepositBoxERC721WithMetadata")?.interface); + const deployedDepositBoxERC721WithMetadata = deployed.get("DepositBoxERC721WithMetadata"); + if (deployedDepositBoxERC721WithMetadata === undefined) { + throw new Error("DepositBoxERC721WithMetadata was not found"); + } + outputObject[getContractKeyInAbiFile("DepositBoxERC721WithMetadata") + "_address"] = deployedDepositBoxERC721WithMetadata.address; + outputObject[getContractKeyInAbiFile("DepositBoxERC721WithMetadata") + "_abi"] = getAbi(deployedDepositBoxERC721WithMetadata.interface); await fs.writeFile("data/proxyMainnet.json", JSON.stringify(outputObject, null, 4)); diff --git a/proxy/migrations/deploySchain.ts b/proxy/migrations/deploySchain.ts index c73d15c21..0bdfb8abf 100644 --- a/proxy/migrations/deploySchain.ts +++ b/proxy/migrations/deploySchain.ts @@ -24,11 +24,10 @@ */ import { promises as fs } from 'fs'; import { Interface } from "ethers/lib/utils"; -import { ethers, artifacts, upgrades } from "hardhat"; +import { ethers, upgrades } from "hardhat"; import hre from "hardhat"; -import { deployLibraries, getLinkedContractFactory } from "./tools/factory"; -import { getAbi } from './tools/abi'; -import { Manifest, hashBytecode } from "@openzeppelin/upgrades-core"; +import { getAbi, getVersion } from '@skalenetwork/upgrade-tools'; +import { Manifest } from "@openzeppelin/upgrades-core"; import { getManifestAdmin } from "@openzeppelin/hardhat-upgrades/dist/admin"; import { Contract } from '@ethersproject/contracts'; import { @@ -40,10 +39,10 @@ import { TokenManagerERC721, TokenManagerEth, TokenManagerLinker, - TokenManagerERC721WithMetadata + TokenManagerERC721WithMetadata, + MessageProxyForSchainWithoutSignature } from '../typechain'; import { TokenManagerERC1155 } from '../typechain/TokenManagerERC1155'; -import { getVersion } from './tools/version'; export function getContractKeyInAbiFile(contract: string): string { if (contract === "MessageProxyForSchain") { @@ -56,34 +55,6 @@ export async function getManifestFile(): Promise { return (await Manifest.forNetwork(ethers.provider)).file;; } -export async function getContractFactory(contract: string) { - const { linkReferences } = await artifacts.readArtifact(contract); - if (!Object.keys(linkReferences).length) - return await ethers.getContractFactory(contract); - - const libraryNames = []; - for (const key of Object.keys(linkReferences)) { - const libraryName = Object.keys(linkReferences[key])[0]; - libraryNames.push(libraryName); - } - - const libraries = await deployLibraries(libraryNames); - const libraryArtifacts: {[key: string]: any} = {}; - for (const libraryName of Object.keys(libraries)) { - const { bytecode } = await artifacts.readArtifact(libraryName); - libraryArtifacts[libraryName] = {"address": libraries[libraryName], "bytecodeHash": hashBytecode(bytecode)}; - } - let manifest: any; - try { - manifest = JSON.parse(await fs.readFile(await getManifestFile(), "utf-8")); - Object.assign(libraryArtifacts, manifest.libraries); - } finally { - Object.assign(manifest, {libraries: libraryArtifacts}); - await fs.writeFile(await getManifestFile(), JSON.stringify(manifest, null, 4)); - } - return await getLinkedContractFactory(contract, libraries); -} - export function getProxyMainnet(contractName: string) { const defaultFilePath = "../data/proxyMainnet.json"; const jsonData = require(defaultFilePath); @@ -154,17 +125,19 @@ async function main() { deployed.set( "KeyStorage", { address: keyStorage.address, interface: keyStorage.interface } ); console.log("Contract KeyStorage deployed to", keyStorage.address); - let messageProxy: Contract; + let messageProxy: MessageProxyForSchain | MessageProxyForSchainWithoutSignature; if( process.env.NO_SIGNATURES === "true" ) { console.log( "Deploy IMA without signature verification" ); console.log("Deploy MessageProxyForSchainWithoutSignature"); - messageProxy = await (await ethers.getContractFactory("MessageProxyForSchainWithoutSignature")).deploy(schainName); + messageProxy = await + (await ethers.getContractFactory("MessageProxyForSchainWithoutSignature")) + .deploy(schainName) as MessageProxyForSchainWithoutSignature; } else { console.log("Deploy MessageProxyForSchain"); messageProxy = await upgrades.deployProxy( await ethers.getContractFactory("MessageProxyForSchain"), [keyStorage.address, schainName] - ); + ) as MessageProxyForSchain; } await messageProxy.deployTransaction.wait(); deployed.set( "MessageProxyForSchain", { address: messageProxy.address, interface: messageProxy.interface } ); @@ -172,7 +145,7 @@ async function main() { try { console.log(`Set version ${version}`) - await (await (messageProxy as MessageProxyForSchain).setVersion(version)).wait(); + await (await messageProxy.setVersion(version)).wait(); } catch { console.log("Failed to set ima version on schain"); } @@ -306,11 +279,21 @@ async function main() { for( const contractName of contracts ) { const propertyName = getContractKeyInAbiFile(contractName); - jsonObjectABI[propertyName + "_address"] = deployed.get( contractName )?.address; - jsonObjectABI[propertyName + "_abi"] = getAbi(deployed.get( contractName )?.interface); + const deployedContract = deployed.get(contractName); + if (deployedContract === undefined) { + throw Error(`Contract ${contractName} was not found`); + } else { + jsonObjectABI[propertyName + "_address"] = deployedContract.address; + jsonObjectABI[propertyName + "_abi"] = getAbi(deployedContract.interface); + } + } + const deployedTokenManagerERC721WithMetadata = deployed.get( "TokenManagerERC721WithMetadata" ); + if (deployedTokenManagerERC721WithMetadata === undefined) { + throw new Error("TokenManagerERC721WithMetadata was not found"); + } else { + jsonObjectABI[getContractKeyInAbiFile("TokenManagerERC721WithMetadata") + "_address"] = deployedTokenManagerERC721WithMetadata.address; + jsonObjectABI[getContractKeyInAbiFile("TokenManagerERC721WithMetadata") + "_abi"] = getAbi(deployedTokenManagerERC721WithMetadata.interface); } - jsonObjectABI[getContractKeyInAbiFile("TokenManagerERC721WithMetadata") + "_address"] = deployed.get( "TokenManagerERC721WithMetadata" )?.address; - jsonObjectABI[getContractKeyInAbiFile("TokenManagerERC721WithMetadata") + "_abi"] = getAbi(deployed.get( "TokenManagerERC721WithMetadata" )?.interface); const erc20OnChainFactory = await ethers.getContractFactory("ERC20OnChain"); jsonObjectABI.ERC20OnChain_abi = getAbi(erc20OnChainFactory.interface); const erc721OnChainFactory = await ethers.getContractFactory("ERC721OnChain"); diff --git a/proxy/migrations/deploySkaleManagerComponents.ts b/proxy/migrations/deploySkaleManagerComponents.ts index 0c35041e1..5d070552b 100644 --- a/proxy/migrations/deploySkaleManagerComponents.ts +++ b/proxy/migrations/deploySkaleManagerComponents.ts @@ -23,10 +23,9 @@ * @copyright SKALE Labs 2021-Present */ import { promises as fs } from 'fs'; -import { ethers, artifacts, web3 } from "hardhat"; -import { deployLibraries, getLinkedContractFactory } from "./tools/factory"; -import { getAbi } from './tools/abi'; -import { Manifest, hashBytecode } from "@openzeppelin/upgrades-core"; +import { ethers, web3 } from "hardhat"; +import { getAbi, getContractFactory } from '@skalenetwork/upgrade-tools'; +import { Manifest } from "@openzeppelin/upgrades-core"; import { KeyStorageMock } from '../typechain/KeyStorageMock'; import { Wallet } from 'ethers'; import { getPublicKey } from '../test/utils/helper'; @@ -39,34 +38,6 @@ export async function getManifestFile(): Promise { return (await Manifest.forNetwork(ethers.provider)).file;; } -export async function getContractFactory(contract: string) { - const { linkReferences } = await artifacts.readArtifact(contract); - if (!Object.keys(linkReferences).length) - return await ethers.getContractFactory(contract); - - const libraryNames = []; - for (const key of Object.keys(linkReferences)) { - const libraryName = Object.keys(linkReferences[key])[0]; - libraryNames.push(libraryName); - } - - const libraries = await deployLibraries(libraryNames); - const libraryArtifacts: {[key: string]: any} = {}; - for (const libraryName of Object.keys(libraries)) { - const { bytecode } = await artifacts.readArtifact(libraryName); - libraryArtifacts[libraryName] = {"address": libraries[libraryName], "bytecodeHash": hashBytecode(bytecode)}; - } - let manifest: any; - try { - manifest = JSON.parse(await fs.readFile(await getManifestFile(), "utf-8")); - Object.assign(libraryArtifacts, manifest.libraries); - } finally { - Object.assign(manifest, {libraries: libraryArtifacts}); - await fs.writeFile(await getManifestFile(), JSON.stringify(manifest, null, 4)); - } - return await getLinkedContractFactory(contract, libraries); -} - async function main() { const [ owner,] = await ethers.getSigners(); @@ -210,4 +181,4 @@ if (require.main === module) { console.error(error); process.exit(1); }); -} \ No newline at end of file +} diff --git a/proxy/migrations/generateManifest.ts b/proxy/migrations/generateManifest.ts index 6b1cc1602..54f28946d 100644 --- a/proxy/migrations/generateManifest.ts +++ b/proxy/migrations/generateManifest.ts @@ -1,7 +1,6 @@ import { ethers } from "hardhat"; import { contracts, getContractKeyInAbiFile } from "./deploySchain"; import { promises as fs } from "fs"; -import { constants } from 'fs'; import { getVersion, getStorageLayout, @@ -12,7 +11,7 @@ import { StorageLayout, isCurrentValidationData } from "@openzeppelin/upgrades-core"; -import { getVersion as version } from "./tools/version"; +import { getVersion as version } from "@skalenetwork/upgrade-tools"; import { ValidationsCacheNotFound, ValidationsCacheOutdated } from "@openzeppelin/hardhat-upgrades/dist/utils"; type Addresses = { diff --git a/proxy/migrations/submitTransactions.ts b/proxy/migrations/submitTransactions.ts index caeb3096a..eeb77f086 100644 --- a/proxy/migrations/submitTransactions.ts +++ b/proxy/migrations/submitTransactions.ts @@ -1,4 +1,4 @@ -import { createMultiSendTransaction, sendSafeTransaction } from "./tools/gnosis-safe"; +import { createMultiSendTransaction, sendSafeTransaction } from "@skalenetwork/upgrade-tools"; import { ethers } from "hardhat"; import { promises as fs } from "fs"; @@ -15,11 +15,6 @@ async function main() { process.exit(1); } - let isSafeMock: boolean = false; - if (process.env.SAFE_MOCK) { - isSafeMock = true; - } - const safe = process.env.SAFE; let privateKey = process.env.PRIVATE_KEY; if (!privateKey.startsWith("0x")) { @@ -27,7 +22,7 @@ async function main() { } const safeTransactions: string[] = JSON.parse(await fs.readFile(process.env.TRANSACTIONS, "utf-8")); - const safeTx = await createMultiSendTransaction(ethers, safe, privateKey, safeTransactions, isSafeMock); + const safeTx = await createMultiSendTransaction(ethers, safe, privateKey, safeTransactions, ethers.provider.network.chainId); const chainId = (await ethers.provider.getNetwork()).chainId; await sendSafeTransaction(safe, chainId, safeTx); console.log("Done"); @@ -40,4 +35,4 @@ if (require.main === module) { console.error(error); process.exit(1); }); -} \ No newline at end of file +} diff --git a/proxy/migrations/tools/abi.ts b/proxy/migrations/tools/abi.ts deleted file mode 100644 index 041ffb47a..000000000 --- a/proxy/migrations/tools/abi.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { Interface } from "ethers/lib/utils"; - -export function getAbi(contractInterface: Interface | undefined) { - if (!contractInterface) { - return undefined; - } - const abi = JSON.parse(contractInterface.format("json") as string); - - abi.forEach((obj: {type: string}) => { - if (obj.type === "function") { - const func = obj as {name: string, type: string, inputs: object[], outputs: object[]}; - func.inputs.concat(func.outputs).forEach((output: object) => { - Object.assign(output, Object.assign({name: ""}, output)); - }) - } - }); - - return abi; -} diff --git a/proxy/migrations/tools/factory.ts b/proxy/migrations/tools/factory.ts deleted file mode 100644 index 7708a269a..000000000 --- a/proxy/migrations/tools/factory.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { ethers, upgrades } from "hardhat"; -import hre from "hardhat"; -import { Artifact } from "hardhat/types"; - -async function getLinkedContractFactory(contractName: string, libraries: any) { - const cArtifact = await hre.artifacts.readArtifact(contractName); - const linkedBytecode = _linkBytecode(cArtifact, libraries); - const ContractFactory = await ethers.getContractFactory(cArtifact.abi, linkedBytecode); - return ContractFactory; -} - -async function deployLibraries(libraryNames: string[]) { - const libraries: any = {}; - for (const libraryName of libraryNames) { - libraries[libraryName] = await _deployLibrary(libraryName); - } - return libraries; -} - -async function _deployLibrary(libraryName: string) { - const Library = await ethers.getContractFactory(libraryName); - const library = await Library.deploy(); - await library.deployed(); - return library.address; -} - -function _linkBytecode(artifact: Artifact, libraries: { [x: string]: any }) { - let bytecode = artifact.bytecode; - for (const [, fileReferences] of Object.entries(artifact.linkReferences)) { - for (const [libName, fixups] of Object.entries(fileReferences)) { - const addr = libraries[libName]; - if (addr === undefined) { - continue; - } - for (const fixup of fixups) { - bytecode = - bytecode.substr(0, 2 + fixup.start * 2) + - addr.substr(2) + - bytecode.substr(2 + (fixup.start + fixup.length) * 2); - } - } - } - return bytecode; -} - -export { - deployLibraries, - getLinkedContractFactory -}; diff --git a/proxy/migrations/tools/gnosis-safe.ts b/proxy/migrations/tools/gnosis-safe.ts deleted file mode 100644 index 1e5013f79..000000000 --- a/proxy/migrations/tools/gnosis-safe.ts +++ /dev/null @@ -1,196 +0,0 @@ -import axios from "axios"; -import { ethers } from "ethers"; -import * as ethUtil from 'ethereumjs-util'; -import chalk from "chalk"; -import { HardhatEthersHelpers } from "@nomiclabs/hardhat-ethers/types"; - -type Ethers = typeof ethers & HardhatEthersHelpers; - -enum Network { - MAINNET = 1, - RINKEBY = 4, - GOERLI = 5, - GANACHE = 1337, - HARDHAT = 31337, -} - -const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000"; - -const ADDRESSES = { - multiSend: { - [Network.MAINNET]: "0x8D29bE29923b68abfDD21e541b9374737B49cdAD", - [Network.RINKEBY]: "0x8D29bE29923b68abfDD21e541b9374737B49cdAD", - [Network.GOERLI]: "0x8D29bE29923b68abfDD21e541b9374737B49cdAD", - }, -} - -const URLS = { - safe_transaction: { - [Network.MAINNET]: "https://safe-transaction.mainnet.gnosis.io", - [Network.RINKEBY]: "https://safe-transaction.rinkeby.gnosis.io", - [Network.GOERLI]: "https://safe-transaction.goerli.gnosis.io", - }, - safe_relay: { - [Network.MAINNET]: "https://safe-relay.mainnet.gnosis.io", - [Network.RINKEBY]: "https://safe-relay.rinkeby.gnosis.io", - [Network.GOERLI]: "https://safe-relay.goerli.gnosis.io", - } -} - -function getMultiSendAddress(chainId: number, isSafeMock: boolean = false) { - if (isSafeMock) { - return ethers.constants.AddressZero; - } else if (chainId === Network.MAINNET) { - return ADDRESSES.multiSend[chainId]; - } else if (chainId === Network.RINKEBY) { - return ADDRESSES.multiSend[chainId]; - } else if (chainId === Network.GOERLI) { - return ADDRESSES.multiSend[chainId]; - } else if ([Network.GANACHE, Network.HARDHAT].includes(chainId)) { - return ethers.constants.AddressZero; - } else { - throw Error("Can't get multiSend contract at network with chainId = " + chainId); - } -} - -export function getSafeTransactionUrl(chainId: number) { - if (chainId === Network.MAINNET) { - return URLS.safe_transaction[chainId]; - } else if (chainId === Network.RINKEBY) { - return URLS.safe_transaction[chainId]; - } else if (chainId === Network.GOERLI) { - return URLS.safe_transaction[chainId]; - } else { - throw Error("Can't get safe-transaction url at network with chainId = " + chainId); - } -} - -export function getSafeRelayUrl(chainId: number) { - if (Object.keys(URLS.safe_relay).includes(chainId.toString())) { - return URLS.safe_relay[chainId as keyof typeof URLS.safe_relay]; - } else { - throw Error("Can't get safe-relay url at network with chainId = " + chainId); - } -} - -function concatTransactions(transactions: string[]) { - return "0x" + transactions.map( (transaction) => { - if (transaction.startsWith("0x")) { - return transaction.slice(2); - } else { - return transaction; - } - }).join(""); -} - -export async function createMultiSendTransaction(ethersProvider: Ethers, safeAddress: string, privateKey: string, transactions: string[], isSafeMock: boolean = false) { - const chainId: number = (await ethersProvider.provider.getNetwork()).chainId; - const multiSendAddress = getMultiSendAddress(chainId, isSafeMock); - const multiSendAbi = [{"constant":false,"inputs":[{"internalType":"bytes","name":"transactions","type":"bytes"}],"name":"multiSend","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}]; - const multiSend = new ethers.Contract(multiSendAddress, new ethers.utils.Interface(multiSendAbi), ethersProvider.provider); - const safeAbi = [{"constant":true,"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"enum Enum.Operation","name":"operation","type":"uint8"},{"internalType":"uint256","name":"safeTxGas","type":"uint256"},{"internalType":"uint256","name":"baseGas","type":"uint256"},{"internalType":"uint256","name":"gasPrice","type":"uint256"},{"internalType":"address","name":"gasToken","type":"address"},{"internalType":"address","name":"refundReceiver","type":"address"},{"internalType":"uint256","name":"_nonce","type":"uint256"}],"name":"getTransactionHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"}]; - interface Safe extends ethers.Contract { - getTransactionHash: ( - to: string, - value: number, - data: string, - operation: number, - safeTxGas: number, - baseGas: number, - gasPrice: number, - gasToken: string, - refundReceiver: string, - nonce: number - ) => Promise - } - const safe = new ethers.Contract(safeAddress, new ethers.utils.Interface(safeAbi), ethersProvider.provider) as Safe; - - let nonce = 0; - if (!isSafeMock) { - try { - const nonceResponse = await axios.get(`${getSafeTransactionUrl(chainId)}/api/v1/safes/${safeAddress}/`); - nonce = nonceResponse.data.nonce; - } catch (e: any) { - if (!e.toString().startsWith("Error: Can't get safe-transaction url")) { - throw e; - } - } - } - - const tx = { - "to": multiSend.address, - "value": 0, // Value in wei - "data": multiSend.interface.encodeFunctionData("multiSend", [ concatTransactions(transactions) ]), - "operation": 1, // 0 CALL, 1 DELEGATE_CALL - "gasToken": ethers.constants.AddressZero, // Token address (hold by the Safe) to be used as a refund to the sender, if `null` is Ether - "safeTxGas": 0, // Max gas to use in the transaction - "baseGas": 0, // Gas costs not related to the transaction execution (signature check, refund payment...) - "gasPrice": 0, // Gas price used for the refund calculation - "refundReceiver": ethers.constants.AddressZero, // Address of receiver of gas payment (or `null` if tx.origin) - "nonce": nonce, // Nonce of the Safe, transaction cannot be executed until Safe's nonce is not equal to this nonce - } - - const digestHex = await safe.getTransactionHash( - tx.to, - tx.value, - tx.data, - tx.operation, - tx.safeTxGas, - tx.baseGas, - tx.gasPrice, - tx.gasToken, - tx.refundReceiver, - tx.nonce - ); - - const privateKeyBuffer = ethUtil.toBuffer(privateKey); - const { r, s, v } = ethUtil.ecsign(ethUtil.toBuffer(digestHex), privateKeyBuffer); - const signature = ethUtil.toRpcSig(v, r, s).toString(); - - const txToSend = { - ...tx, - "contractTransactionHash": digestHex, // Contract transaction hash calculated from all the field - // Owner of the Safe proposing the transaction. Must match one of the signatures - "sender": ethers.utils.getAddress(ethUtil.bufferToHex(ethUtil.privateToAddress(privateKeyBuffer))), - "signature": signature, // One or more ethereum ECDSA signatures of the `contractTransactionHash` as an hex string - "origin": "Upgrade IMA" // Give more information about the transaction, e.g. "My Custom Safe app" - } - - return txToSend; -} - -export async function sendSafeTransaction(safe: string, chainId: number, safeTx: any) { - try { - console.log("Estimate gas"); - const estimateRequest = (({ - to, - value, - data, - operation, - gasToken - }) => ({ to, value, data, operation, gasToken }))(safeTx); - - try { - const estimateResponse = await axios.post( - `${getSafeRelayUrl(chainId)}/api/v2/safes/${safe}/transactions/estimate/`, - estimateRequest - ); - console.log(chalk.cyan(`Recommend to set gas limit to ${ - parseInt(estimateResponse.data.safeTxGas, 10) + parseInt(estimateResponse.data.baseGas, 10)}`)); - } catch (e: any) { - console.log(chalk.red("Failed to estimate gas")); - console.log(e.toString()); - } - - console.log(chalk.green("Send transaction to gnosis safe")); - await axios.post(`${getSafeTransactionUrl(chainId)}/api/v1/safes/${safe}/transactions/`, safeTx) - } catch (e: any) { - if (e.response) { - console.log(JSON.stringify(e.response.data, null, 4)) - console.log(chalk.red(`Request failed with ${e.response.status} code`)); - } else { - console.log(chalk.red("Request failed with unknown reason")); - } - throw e; - } -} \ No newline at end of file diff --git a/proxy/migrations/tools/multiSend.ts b/proxy/migrations/tools/multiSend.ts deleted file mode 100644 index 1d5e2d16a..000000000 --- a/proxy/migrations/tools/multiSend.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { BigNumber } from "ethers"; - -function padWithZeros(value: string, targetLength: number) { - return ("0".repeat(targetLength) + value).slice(-targetLength); -} - -export function encodeTransaction(operation: 0 | 1, to: string, value: BigNumber | number, data: string) { - /// operation as a uint8 with 0 for a call or 1 for a delegatecall (=> 1 byte), - /// to as a address (=> 20 bytes), - /// value as a uint256 (=> 32 bytes), - /// data length as a uint256 (=> 32 bytes), - /// data as bytes. - - let _operation; - if (operation === 0) { - _operation = "00"; - } else if (operation === 1) { - _operation = "01"; - } else { - throw Error(`Operation ${operation} is not a correct value`); - } - - let _to = to; - if (to.startsWith("0x")) { - _to = _to.slice(2); - } - _to = padWithZeros(_to, 20 * 2); - - const _value = padWithZeros(BigNumber.from(value).toHexString().slice(2), 32 * 2); - - let _data = data; - if (data.startsWith("0x")) { - _data = _data.slice(2); - } - if (_data.length % 2 !== 0) { - _data = "0" + _data; - } - - const _dataLength = padWithZeros((_data.length / 2).toString(16), 32 * 2); - - return "0x" + [ - _operation, - _to, - _value, - _dataLength, - _data, - ].join(""); -} \ No newline at end of file diff --git a/proxy/migrations/tools/verification.ts b/proxy/migrations/tools/verification.ts deleted file mode 100644 index 6373c6741..000000000 --- a/proxy/migrations/tools/verification.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { ethers, run, network } from "hardhat"; -import chalk from "chalk"; -import { getImplementationAddress } from "@openzeppelin/upgrades-core"; - -export async function verify(contractName: string, contractAddress: string, constructorArguments: object) { - if (![1337, 31337].includes((await ethers.provider.getNetwork()).chainId)) { - for (let retry = 0; retry <= 5; ++retry) { - try { - await run("verify:verify", { - address: contractAddress, - constructorArguments - }); - break; - } catch (e: any) { - if (e.toString().includes("Contract source code already verified")) { - console.log(chalk.grey(`${contractName} is already verified`)); - return; - } - console.log(chalk.red(`Contract ${contractName} was not verified on etherscan`)); - console.log(e.toString()); - } - } - } -} - -export async function verifyProxy(contractName: string, proxyAddress: string, constructorArguments: object) { - await verify(contractName, await getImplementationAddress(network.provider, proxyAddress), constructorArguments); -} \ No newline at end of file diff --git a/proxy/migrations/tools/version.ts b/proxy/migrations/tools/version.ts deleted file mode 100644 index 642345c7d..000000000 --- a/proxy/migrations/tools/version.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { promises as fs } from 'fs'; -import { exec as asyncExec } from "child_process"; -import util from 'util'; -const exec = util.promisify(asyncExec); - -export async function getVersion() { - if (process.env.VERSION) { - return process.env.VERSION; - } - try { - const tag = (await exec("git describe --tags")).stdout.trim(); - return tag; - } catch { - return (await fs.readFile("../VERSION", "utf-8")).trim(); - } -} diff --git a/proxy/migrations/transferOwnership.ts b/proxy/migrations/transferOwnership.ts index 5cb8ad2c8..c7010cb2d 100644 --- a/proxy/migrations/transferOwnership.ts +++ b/proxy/migrations/transferOwnership.ts @@ -1,8 +1,7 @@ -import { contracts, getContractKeyInAbiFile, getManifestFile } from "./deployMainnet"; -import { ethers, network, upgrades, artifacts } from "hardhat"; +import { contracts, getContractKeyInAbiFile } from "./deployMainnet"; +import { ethers } from "hardhat"; import hre from "hardhat"; import { promises as fs } from "fs"; -import { deployLibraries, getLinkedContractFactory } from "./tools/factory"; import { getManifestAdmin } from "@openzeppelin/hardhat-upgrades/dist/admin"; import chalk from "chalk"; import { SafeMock } from "../typechain"; diff --git a/proxy/migrations/upgradeMainnet.ts b/proxy/migrations/upgradeMainnet.ts index b453d7482..4340aa03c 100644 --- a/proxy/migrations/upgradeMainnet.ts +++ b/proxy/migrations/upgradeMainnet.ts @@ -52,7 +52,7 @@ async function main() { await manifestSetup(pathToManifest); const upgrader = new ImaMainnetUpgrader( "proxyMainnet", - "1.3.4", + "1.4.0", await getImaMainnetAbiAndAddress(), contracts ); diff --git a/proxy/migrations/upgradeSchain.ts b/proxy/migrations/upgradeSchain.ts index a7419340a..7c850bfef 100644 --- a/proxy/migrations/upgradeSchain.ts +++ b/proxy/migrations/upgradeSchain.ts @@ -72,7 +72,7 @@ async function main() { await manifestSetup(pathToManifest); const upgrader = new ImaSchainUpgrader( "proxySchain", - "1.3.4", + "1.4.0", await getImaSchainAbiAndAddress(), contracts ); diff --git a/proxy/package.json b/proxy/package.json index 19a2ea24d..2c3cb5ac5 100644 --- a/proxy/package.json +++ b/proxy/package.json @@ -7,8 +7,8 @@ "compile": "npx hardhat compile", "cleanCompile": "npx hardhat clean && yarn compile", "deploy-to-both-chains": "yarn deploy-to-mainnet && yarn deploy-to-schain", - "deploy-to-mainnet": "npx hardhat run migrations/deployMainnet.ts --network mainnet", - "deploy-to-schain": "npx hardhat run migrations/deploySchain.ts --network schain", + "deploy-to-mainnet": "VERSION=$(cat ../VERSION) npx hardhat run migrations/deployMainnet.ts --network mainnet", + "deploy-to-schain": "VERSION=$(cat ../VERSION) npx hardhat run migrations/deploySchain.ts --network schain", "deploy-skale-manager-components": "npx hardhat run migrations/deploySkaleManagerComponents.ts --network mainnet", "lint": "npx solhint \"contracts/**/*.sol\"", "prepare": "yarn cleanCompile", @@ -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.1.0-develop.0", + "@skalenetwork/ima-interfaces": "^2.0.0-beta.0", "@skalenetwork/skale-manager-interfaces": "1.0.0-develop.1", "@skalenetwork/upgrade-tools": "2.0.0-refactor.15", "axios": "^0.21.4", diff --git a/proxy/scripts/magic_upgrade.sh b/proxy/scripts/magic_upgrade.sh index d5348cc2d..c56fa379c 100755 --- a/proxy/scripts/magic_upgrade.sh +++ b/proxy/scripts/magic_upgrade.sh @@ -25,22 +25,22 @@ fi IMA_RELEASES_URL="https://github.com/skalenetwork/IMA/releases/download/" cd data/ -rm -f ima-$DEPLOYED_VERSION-predeployed-abi.json -wget $IMA_RELEASES_URL/$DEPLOYED_VERSION/ima-$DEPLOYED_VERSION-predeployed-abi.json +rm -f "ima-$DEPLOYED_VERSION-predeployed-abi.json" +wget "$IMA_RELEASES_URL/$DEPLOYED_VERSION/ima-$DEPLOYED_VERSION-predeployed-abi.json" cd ../scripts/ -wget $IMA_RELEASES_URL/$DEPLOYED_VERSION/ima-schain-$DEPLOYED_VERSION-manifest.json -python3 updateManifest.py ima-schain-$DEPLOYED_VERSION-manifest.json -mv ima-schain-$DEPLOYED_VERSION-manifest.json ../.openzeppelin/unknown-$SCHAIN_ID.json +wget "$IMA_RELEASES_URL/$DEPLOYED_VERSION/ima-schain-$DEPLOYED_VERSION-manifest.json" +python3 updateManifest.py "ima-schain-$DEPLOYED_VERSION-manifest.json" +mv "ima-schain-$DEPLOYED_VERSION-manifest.json" "../.openzeppelin/unknown-$SCHAIN_ID.json" cd .. git clone https://github.com/skalenetwork/skale-network.git MAINNET_STABLE_IMA_VERSION=$(ls skale-network/releases/mainnet/IMA/ | sort -r | head -n 1) -cp skale-network/releases/mainnet/IMA/$MAINNET_STABLE_IMA_VERSION/mainnet/abi.json data/ima-$MAINNET_STABLE_IMA_VERSION-mainnet-abi.json +cp "skale-network/releases/mainnet/IMA/$MAINNET_STABLE_IMA_VERSION/mainnet/abi.json" "data/ima-$MAINNET_STABLE_IMA_VERSION-mainnet-abi.json" rm -r --interactive=never skale-network/ if [[ $MAINNET_CHAIN_ID != "1" ]]; then if [[ $MESSAGE_PROXY_MAINNET_ADDRESS ]]; then - sed -i '2s/.*/ "message_proxy_mainnet_address": "'"$MESSAGE_PROXY_MAINNET_ADDRESS"'",/' data/ima-$MAINNET_STABLE_IMA_VERSION-mainnet-abi.json + sed -i '2s/.*/ "message_proxy_mainnet_address": "'"$MESSAGE_PROXY_MAINNET_ADDRESS"'",/' "data/ima-$MAINNET_STABLE_IMA_VERSION-mainnet-abi.json" else echo "Set MESSAGE_PROXY_MAINNET_ADDRESS" exit 1 diff --git a/proxy/scripts/test_upgrade.sh b/proxy/scripts/test_upgrade.sh index b6cbbd30b..3711481ce 100755 --- a/proxy/scripts/test_upgrade.sh +++ b/proxy/scripts/test_upgrade.sh @@ -32,9 +32,6 @@ PRIVATE_KEY_FOR_SCHAIN=$(cat "$ACCOUNTS_FILENAME" | jq -r '.private_keys | to_en CHAIN_NAME_SCHAIN="Test" VERSION="$DEPLOYED_VERSION" PRIVATE_KEY_FOR_ETHEREUM="$PRIVATE_KEY_FOR_ETHEREUM" PRIVATE_KEY_FOR_SCHAIN="$PRIVATE_KEY_FOR_SCHAIN" npx hardhat run migrations/deploySkaleManagerComponents.ts --network localhost VERSION="$DEPLOYED_VERSION" npx hardhat run migrations/deployMainnet.ts --network localhost CHAIN_NAME_SCHAIN="Test" VERSION="$DEPLOYED_VERSION" npx hardhat run migrations/deploySchain.ts --network localhost -cp "$GITHUB_WORKSPACE/proxy/migrations/generateManifest.ts" ./migrations/generateManifest.ts -cp "$GITHUB_WORKSPACE/proxy/migrations/changeManifest.ts" ./migrations/changeManifest.ts -cp "$GITHUB_WORKSPACE/proxy/migrations/tools/version.ts" ./migrations/tools/version.ts ABI_FILENAME_SCHAIN="proxySchain_Test.json" ABI="data/$ABI_FILENAME_SCHAIN" \ diff --git a/proxy/scripts/upgrade_instruction.md b/proxy/scripts/upgrade-instruction.md similarity index 72% rename from proxy/scripts/upgrade_instruction.md rename to proxy/scripts/upgrade-instruction.md index 42269c3fe..4c9bf8929 100644 --- a/proxy/scripts/upgrade_instruction.md +++ b/proxy/scripts/upgrade-instruction.md @@ -1,36 +1,51 @@ # Step-by-step guide for upgrading IMA contracts on Schain side ## Install project + Git clone and run yarn install in the root of the project. + ```bash git clone https://github.com/skalenetwork/IMA.git && cd IMA/ && yarn install ``` + ## Prepare environment + Create `.env` file by path `IMA/proxy/`. Now you need to create new account. You can generate it in Metamask. Next export private key and put it in `.env` as `PRIVATE_KEY` without 0x. Also put endpoint of your chain as `ENDPOINT` to the `.env`. Also you need to add this account to your Gnosis Wallet as one of the Safe owners. Open Gnosis app, go to "Settings", click "Add new owner" and then sign transaction. Example of `.env` file: + ```bash ENDPOINT="http://127.0.0.1:8545" PRIVATE_KEY="0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" ``` + ## Grant role + Next you need to grant `DEPLOYER_ROLE` for account that we have created in previous step for being able to deploy new contracts on chain. One of the easiest ways to do this would be to use the Blockscout interface. First you need to find the `ConfigController` contract, its address is `0xD200200000000000000000000000000000000d2`, click `Write Proxy` connect the wallet on which there is sFUEL, find the `addToWhitelist` function and enter the address of the new account that you generated in the metamask, then click Write and confirm the transaction in the metamask. + ## Get sFUEL + Now you need to get some sFUEL on your new account. To do this, you need to use a contract that distributes sFUEL - `Etherbase`. Also you can get sFUEL from faucet available on your chain - look on [sFUEL Station](https://sfuel.skale.network). As in the previous step, you can use Blockscout or transfer a sufficient amount of sFUEL to the wallet you created earlier. In order to do this in Blockscout, you need to go to `0xd2bA3e0000000000000000000000000000000000` and find the `partiallyRetrieve` function, there will be two fields. In the "receiver" field, you need to enter the sFUEL recipient, that is, the wallet address that you generated earlier. In the "amount" field, enter the amount of sFUEL in Wei. It is important to note that only the owner of the chain can perform this transaction. + ## Switch to desired version + Before running the upgrade script, you need to switch to the desired version. The example below allows you to switch to the latest stable version. + ```bash git checkout stable && yarn install ``` + ## Run upgrade script -* `DEPLOYED_VERSION` - current version of your IMA contracts. Example: `DEPLOYED_VERSION="1.1.3-beta.0"` -* `SCHAIN_ID` - chainId of SKALE chain. -* `SCHAIN_NAME` - name of SKALE chain. -* `SAFE_ADDRESS` - address of gnosis safe wallet on mainnet. -* `MAINNET_CHAIN_ID` - chainId, use 1 for Ethereum mainnet or 5 for Goerli. -* `MESSAGE_PROXY_MAINNET_ADDRESS` - address of MessageProxyForMainnet contract. Optional parameter. Required only if you have deployed IMA on Goerli Testnet. -* `ALLOW_NOT_ATOMIC_UPGRADE` - means that the transaction on the chain will not be executed atomically. That is, for example, if you send two transactions, there is a non-zero probability that they will be written to different blocks. Enter "OK" if you agree. -* `VERSION` - version to upgrade to. Optional parametr. Leave this parameter empty if you are not sure which version you are updating to, the script will automatically take the correct version. + +* `DEPLOYED_VERSION` - current version of your IMA contracts. Example: `DEPLOYED_VERSION="1.1.3-beta.0"` +* `SCHAIN_ID` - chainId of SKALE chain. +* `SCHAIN_NAME` - name of SKALE chain. +* `SAFE_ADDRESS` - address of gnosis safe wallet on mainnet. +* `MAINNET_CHAIN_ID` - chainId, use 1 for Ethereum mainnet or 5 for Goerli. +* `MESSAGE_PROXY_MAINNET_ADDRESS` - address of MessageProxyForMainnet contract. Optional parameter. Required only if you have deployed IMA on Goerli Testnet. +* `ALLOW_NOT_ATOMIC_UPGRADE` - means that the transaction on the chain will not be executed atomically. That is, for example, if you send two transactions, there is a non-zero probability that they will be written to different blocks. Enter "OK" if you agree. +* `VERSION` - version to upgrade to. Optional parametr. Leave this parameter empty if you are not sure which version you are updating to, the script will automatically take the correct version. Run the upgrade script in `IMA/proxy/` with the above parameters. + ```bash ./scripts/magic_upgrade.sh ``` diff --git a/proxy/test/DepositBoxERC1155.ts b/proxy/test/DepositBoxERC1155.ts index a5627f629..831d4891a 100644 --- a/proxy/test/DepositBoxERC1155.ts +++ b/proxy/test/DepositBoxERC1155.ts @@ -84,8 +84,10 @@ describe("DepositBoxERC1155", () => { let messageProxy: MessageProxyForMainnet; let linker: Linker; let communityPool: CommunityPool; + let messages: MessagesTester; const contractManagerAddress = "0x0000000000000000000000000000000000000000"; const schainName = "Schain"; + const schainHash = stringValue(web3.utils.soliditySha3(schainName)); before(async () => { [deployer, user, user2, richGuy] = await ethers.getSigners(); @@ -105,6 +107,7 @@ describe("DepositBoxERC1155", () => { linker = await deployLinker(contractManager, messageProxy); depositBoxERC1155 = await deployDepositBoxERC1155(contractManager, linker, messageProxy); communityPool = await deployCommunityPool(contractManager, linker, messageProxy); + messages = await deployMessages(); await messageProxy.grantRole(await messageProxy.CHAIN_CONNECTOR_ROLE(), linker.address); await messageProxy.grantRole(await messageProxy.EXTRA_CONTRACT_REGISTRAR_ROLE(), deployer.address); await initializeSchain(contractManager, schainName, user.address, 1, 1); @@ -220,6 +223,45 @@ describe("DepositBoxERC1155", () => { expect(BigNumber.from(await erc1155.balanceOf(depositBoxERC1155.address, id2)).toNumber()).to.equal(amount2); }); + it("should invoke `depositERC1155Direct` without mistakes", async () => { + // preparation + const contractHere = erc1155.address; + const to = user.address; + const id = 5; + const amount = 7; + const id2 = 10; + const amount2 = 3; + // the wei should be MORE than (55000 * 1000000000) + // GAS_AMOUNT_POST_MESSAGE * AVERAGE_TX_PRICE constants in DepositBox.sol + // add schain to avoid the `Unconnected chain` error + await linker + .connect(deployer) + .connectSchain(schainName, [deployer.address, deployer.address, deployer.address]); + // transfer tokenId from `deployer` to `depositBoxERC1155` + await erc1155.connect(deployer).setApprovalForAll(depositBoxERC1155.address, true); + // execution + await depositBoxERC1155 + .connect(deployer) + .depositERC1155Direct(schainName, contractHere, id, amount, to).should.be.eventually.rejectedWith("Whitelist is enabled"); + await depositBoxERC1155.connect(user).disableWhitelist(schainName); + const data1 = await messages.encodeTransferErc1155AndTokenInfoMessage(contractHere, to, id, amount, { uri: "New ERC1155 Token" }); + const data2 = await messages.encodeTransferErc1155Message(contractHere, to, id2, amount2); + await depositBoxERC1155 + .connect(deployer) + .depositERC1155Direct(schainName, contractHere, id, amount, to) + .should.emit(messageProxy, "OutgoingMessage") + .withArgs(schainHash, 0, depositBoxERC1155.address, deployer.address, data1); + await depositBoxERC1155 + .connect(deployer) + .depositERC1155Direct(schainName, contractHere, id2, amount2, to) + .should.emit(messageProxy, "OutgoingMessage") + .withArgs(schainHash, 1, depositBoxERC1155.address, deployer.address, data2); + // console.log("Gas for depositERC1155:", res.receipt.gasUsed); + // expectation + expect(BigNumber.from(await erc1155.balanceOf(depositBoxERC1155.address, id)).toNumber()).to.equal(amount); + expect(BigNumber.from(await erc1155.balanceOf(depositBoxERC1155.address, id2)).toNumber()).to.equal(amount2); + }); + it("should rejected with `DepositBox was not approved for ERC1155 token Batch`", async () => { // preparation const error = "DepositBox was not approved for ERC1155 token Batch"; @@ -284,6 +326,55 @@ describe("DepositBoxERC1155", () => { expect(balanceIdsNumber).to.deep.equal(amounts); expect(balanceIds2Number).to.deep.equal(amounts2); }); + + it("should invoke `depositERC1155BatchDirect` without mistakes", async () => { + // preparation + const contractHere = erc1155.address; + const to = user.address; + const ids = [1, 2, 3]; + const amounts = [3, 2, 1]; + const ids2 = [5, 4, 99]; + const amounts2 = [9, 77, 888]; + // the wei should be MORE than (55000 * 1000000000) + // GAS_AMOUNT_POST_MESSAGE * AVERAGE_TX_PRICE constants in DepositBox.sol + // add schain to avoid the `Unconnected chain` error + await linker + .connect(deployer) + .connectSchain(schainName, [deployer.address, deployer.address, deployer.address]); + // transfer tokenId from `deployer` to `depositBoxERC1155` + await erc1155.connect(deployer).setApprovalForAll(depositBoxERC1155.address, true); + // execution + await depositBoxERC1155 + .connect(deployer) + .depositERC1155BatchDirect(schainName, contractHere, ids, amounts, to).should.be.eventually.rejectedWith("Whitelist is enabled"); + await depositBoxERC1155.connect(user).disableWhitelist(schainName); + const data1 = await messages.encodeTransferErc1155BatchAndTokenInfoMessage(contractHere, to, ids, amounts, { uri: "New ERC1155 Token" }); + const data2 = await messages.encodeTransferErc1155BatchMessage(contractHere, to, ids2, amounts2); + await depositBoxERC1155 + .connect(deployer) + .depositERC1155BatchDirect(schainName, contractHere, ids, amounts, to) + .should.emit(messageProxy, "OutgoingMessage") + .withArgs(schainHash, 0, depositBoxERC1155.address, deployer.address, data1); + await depositBoxERC1155 + .connect(deployer) + .depositERC1155BatchDirect(schainName, contractHere, ids2, amounts2, to) + .should.emit(messageProxy, "OutgoingMessage") + .withArgs(schainHash, 1, depositBoxERC1155.address, deployer.address, data2); + // console.log("Gas for depositERC1155:", res.receipt.gasUsed); + // expectation + const balanceIds = await erc1155.balanceOfBatch([depositBoxERC1155.address, depositBoxERC1155.address, depositBoxERC1155.address], ids); + const balanceIds2 = await erc1155.balanceOfBatch([depositBoxERC1155.address, depositBoxERC1155.address, depositBoxERC1155.address], ids2); + const balanceIdsNumber: number[] = []; + const balanceIds2Number: number[] = []; + balanceIds.forEach(element => { + balanceIdsNumber.push(BigNumber.from(element).toNumber()) + }); + balanceIds2.forEach(element => { + balanceIds2Number.push(BigNumber.from(element).toNumber()) + }); + expect(balanceIdsNumber).to.deep.equal(amounts); + expect(balanceIds2Number).to.deep.equal(amounts2); + }); }); it("should get funds after kill", async () => { @@ -322,11 +413,9 @@ describe("DepositBoxERC1155", () => { describe("tests for `postMessage` function", async () => { let erc1155: ERC1155OnChain; - let messages: MessagesTester; beforeEach(async () => { erc1155 = await deployERC1155OnChain("New ERC1155 Token"); - messages = await deployMessages(); }); it("should transfer ERC1155 token", async () => { diff --git a/proxy/test/DepositBoxERC20.ts b/proxy/test/DepositBoxERC20.ts index 6b37c51ad..54d1fe14f 100644 --- a/proxy/test/DepositBoxERC20.ts +++ b/proxy/test/DepositBoxERC20.ts @@ -85,6 +85,7 @@ describe("DepositBoxERC20", () => { let messageProxy: MessageProxyForMainnet; let linker: Linker; let communityPool: CommunityPool; + let messages: MessagesTester; const contractManagerAddress = "0x0000000000000000000000000000000000000000"; const schainName = "Schain"; const schainHash = ethers.utils.solidityKeccak256(["string"], [schainName]); @@ -125,6 +126,7 @@ describe("DepositBoxERC20", () => { await messageProxy.registerExtraContractForAll(depositBoxERC20.address); await messageProxy.registerExtraContract(schainName, communityPool.address); await messageProxy.registerExtraContract(schainName, linker.address); + messages = await deployMessages(); }); describe("tests with `ERC20`", async () => { @@ -184,6 +186,32 @@ describe("DepositBoxERC20", () => { .depositERC20(schainName, erc20.address, 1); }); + it("should invoke `depositERC20Direct` without mistakes", async () => { + // preparation + // mint some quantity of ERC20 tokens for `deployer` address + const amount = 10; + await erc20.connect(deployer).mint(deployer.address, amount); + await erc20.connect(deployer).approve(depositBoxERC20.address, amount); + // execution + await depositBoxERC20 + .connect(deployer) + .depositERC20Direct(schainName, erc20.address, 1, user.address).should.be.eventually.rejectedWith("Whitelist is enabled"); + await depositBoxERC20.connect(schainOwner).disableWhitelist(schainName); + const data1 = await messages.encodeTransferErc20AndTokenInfoMessage(erc20.address, user.address, 1, amount, { name: "D2-token", symbol: "D2", decimals: 18 }); + const data2 = await messages.encodeTransferErc20AndTotalSupplyMessage(erc20.address, user.address, 1, amount); + await depositBoxERC20 + .connect(deployer) + .depositERC20Direct(schainName, erc20.address, 1, user.address) + .should.emit(messageProxy, "OutgoingMessage") + .withArgs(schainHash, 0, depositBoxERC20.address, deployer.address, data1); + + await depositBoxERC20 + .connect(deployer) + .depositERC20Direct(schainName, erc20.address, 1, user.address) + .should.emit(messageProxy, "OutgoingMessage") + .withArgs(schainHash, 1, depositBoxERC20.address, deployer.address, data2); + }); + it("should rejected with `Amount is incorrect`", async () => { // preparation // mint some quantity of ERC20 tokens for `deployer` address @@ -274,14 +302,12 @@ describe("DepositBoxERC20", () => { let erc20Clone: ERC20OnChain; let eRC721OnChain: ERC721OnChain; let eRC1155OnChain: ERC1155OnChain; - let messages: MessagesTester; beforeEach(async () => { erc20 = await deployERC20OnChain("D2-token", "D2",); erc20Clone = await deployERC20OnChain("Token", "T",); eRC721OnChain = await deployERC721OnChain("ERC721OnChain", "ERC721"); eRC1155OnChain = await deployERC1155OnChain("New ERC1155 Token"); - messages = await deployMessages(); }); it("should transfer ERC20 token", async () => { diff --git a/proxy/test/DepositBoxERC721.ts b/proxy/test/DepositBoxERC721.ts index 9088cb31d..ac1948ce9 100644 --- a/proxy/test/DepositBoxERC721.ts +++ b/proxy/test/DepositBoxERC721.ts @@ -84,8 +84,10 @@ describe("DepositBoxERC721", () => { let messageProxy: MessageProxyForMainnet; let linker: Linker; let communityPool: CommunityPool; + let messages: MessagesTester; const contractManagerAddress = "0x0000000000000000000000000000000000000000"; const schainName = "Schain"; + const schainHash = stringValue(web3.utils.soliditySha3(schainName)); before(async () => { [deployer, user, user2, richGuy] = await ethers.getSigners(); @@ -105,6 +107,7 @@ describe("DepositBoxERC721", () => { linker = await deployLinker(contractManager, messageProxy); depositBoxERC721 = await deployDepositBoxERC721(contractManager, linker, messageProxy); communityPool = await deployCommunityPool(contractManager, linker, messageProxy); + messages = await deployMessages(); await messageProxy.grantRole(await messageProxy.CHAIN_CONNECTOR_ROLE(), linker.address); await messageProxy.grantRole(await messageProxy.EXTRA_CONTRACT_REGISTRAR_ROLE(), deployer.address); await initializeSchain(contractManager, schainName, user.address, 1, 1); @@ -204,6 +207,44 @@ describe("DepositBoxERC721", () => { expect(await erc721OnChain.ownerOf(tokenId2)).to.equal(depositBoxERC721.address); }); + it("should invoke `depositERC721Direct` without mistakes", async () => { + // preparation + const contractHere = erc721OnChain.address; + const to = user.address; + const tokenId = 10; + const tokenId2 = 11; + // the wei should be MORE than (55000 * 1000000000) + // GAS_AMOUNT_POST_MESSAGE * AVERAGE_TX_PRICE constants in DepositBox.sol + // add schain to avoid the `Unconnected chain` error + await linker + .connect(deployer) + .connectSchain(schainName, [deployer.address, deployer.address, deployer.address]); + // transfer tokenId from `deployer` to `depositBoxERC721` + await erc721OnChain.connect(deployer).approve(depositBoxERC721.address, tokenId); + await erc721OnChain.connect(deployer).approve(depositBoxERC721.address, tokenId2); + // execution + await depositBoxERC721 + .connect(deployer) + .depositERC721Direct(schainName, contractHere, tokenId, to).should.be.eventually.rejectedWith("Whitelist is enabled"); + await depositBoxERC721.connect(user).disableWhitelist(schainName); + const data1 = await messages.encodeTransferErc721AndTokenInfoMessage(contractHere, to, tokenId, { name: "ERC721OnChain", symbol: "ERC721" }); + const data2 = await messages.encodeTransferErc721Message(contractHere, to, tokenId2); + await depositBoxERC721 + .connect(deployer) + .depositERC721Direct(schainName, contractHere, tokenId, to) + .should.emit(messageProxy, "OutgoingMessage") + .withArgs(schainHash, 0, depositBoxERC721.address, deployer.address, data1); + await depositBoxERC721 + .connect(deployer) + .depositERC721Direct(schainName, contractHere, tokenId2, to) + .should.emit(messageProxy, "OutgoingMessage") + .withArgs(schainHash, 1, depositBoxERC721.address, deployer.address, data2);; + // console.log("Gas for depositERC721:", res.receipt.gasUsed); + // expectation + expect(await erc721OnChain.ownerOf(tokenId)).to.equal(depositBoxERC721.address); + expect(await erc721OnChain.ownerOf(tokenId2)).to.equal(depositBoxERC721.address); + }); + }); it("should get funds after kill", async () => { @@ -246,7 +287,6 @@ describe("DepositBoxERC721", () => { describe("tests for `postMessage` function", async () => { let erc721: ERC721OnChain; let erc721OnChain: ERC721OnChain; - let messages: MessagesTester; let weiAmount: string; let sign: { blsSignature: [BigNumber, BigNumber], @@ -259,7 +299,6 @@ describe("DepositBoxERC721", () => { weiAmount = 1e18.toString(); erc721 = await deployERC721OnChain("ERC721", "ERC721"); erc721OnChain = await deployERC721OnChain("ERC721OnChain", "ERC721OnChain"); - messages = await deployMessages(); sign = { blsSignature: BlsSignature, @@ -356,7 +395,6 @@ describe("DepositBoxERC721", () => { // preparation const tokenId = 10; const to = user.address; - const schainHash = stringValue(web3.utils.soliditySha3(schainName)); const zeroHash = "0x0000000000000000000000000000000000000000000000000000000000000000"; const senderFromSchain = deployer.address; diff --git a/proxy/test/DepositBoxERC721WithMetadata.ts b/proxy/test/DepositBoxERC721WithMetadata.ts index 1c8119d93..b803da47b 100644 --- a/proxy/test/DepositBoxERC721WithMetadata.ts +++ b/proxy/test/DepositBoxERC721WithMetadata.ts @@ -84,8 +84,10 @@ describe("DepositBoxERC721WithMetadata", () => { let messageProxy: MessageProxyForMainnet; let linker: Linker; let communityPool: CommunityPool; + let messages: MessagesTester; const contractManagerAddress = "0x0000000000000000000000000000000000000000"; const schainName = "Schain"; + const schainHash = stringValue(web3.utils.soliditySha3(schainName)); before(async () => { [deployer, user, user2, richGuy] = await ethers.getSigners(); @@ -105,6 +107,7 @@ describe("DepositBoxERC721WithMetadata", () => { linker = await deployLinker(contractManager, messageProxy); depositBoxERC721WithMetadata = await deployDepositBoxERC721WithMetadata(contractManager, linker, messageProxy); communityPool = await deployCommunityPool(contractManager, linker, messageProxy); + messages = await deployMessages(); await messageProxy.grantRole(await messageProxy.CHAIN_CONNECTOR_ROLE(), linker.address); await messageProxy.grantRole(await messageProxy.EXTRA_CONTRACT_REGISTRAR_ROLE(), deployer.address); await initializeSchain(contractManager, schainName, user.address, 1, 1); @@ -208,6 +211,44 @@ describe("DepositBoxERC721WithMetadata", () => { expect(await erc721OnChain.ownerOf(tokenId2)).to.equal(depositBoxERC721WithMetadata.address); }); + it("should invoke `depositERC721Direct` without mistakes", async () => { + // preparation + const contractHere = erc721OnChain.address; + const to = user.address; + const tokenId = 10; + const tokenId2 = 11; + // the wei should be MORE than (55000 * 1000000000) + // GAS_AMOUNT_POST_MESSAGE * AVERAGE_TX_PRICE constants in DepositBox.sol + // add schain to avoid the `Unconnected chain` error + await linker + .connect(deployer) + .connectSchain(schainName, [deployer.address, deployer.address, deployer.address]); + // transfer tokenId from `deployer` to `depositBoxERC721` + await erc721OnChain.connect(deployer).approve(depositBoxERC721WithMetadata.address, tokenId); + await erc721OnChain.connect(deployer).approve(depositBoxERC721WithMetadata.address, tokenId2); + // execution + await depositBoxERC721WithMetadata + .connect(deployer) + .depositERC721Direct(schainName, contractHere, tokenId, to).should.be.eventually.rejectedWith("Whitelist is enabled"); + await depositBoxERC721WithMetadata.connect(user).disableWhitelist(schainName); + const data1 = await messages.encodeTransferErc721WithMetadataAndTokenInfoMessage(contractHere, to, tokenId, "Hello10", { name: "ERC721OnChain", symbol: "ERC721" }); + const data2 = await messages.encodeTransferErc721MessageWithMetadata(contractHere, to, tokenId2, "Hello11"); + await depositBoxERC721WithMetadata + .connect(deployer) + .depositERC721Direct(schainName, contractHere, tokenId, to) + .should.emit(messageProxy, "OutgoingMessage") + .withArgs(schainHash, 0, depositBoxERC721WithMetadata.address, deployer.address, data1); + await depositBoxERC721WithMetadata + .connect(deployer) + .depositERC721Direct(schainName, contractHere, tokenId2, to) + .should.emit(messageProxy, "OutgoingMessage") + .withArgs(schainHash, 1, depositBoxERC721WithMetadata.address, deployer.address, data2);; + // console.log("Gas for depositERC721:", res.receipt.gasUsed); + // expectation + expect(await erc721OnChain.ownerOf(tokenId)).to.equal(depositBoxERC721WithMetadata.address); + expect(await erc721OnChain.ownerOf(tokenId2)).to.equal(depositBoxERC721WithMetadata.address); + }); + }); it("should get funds after kill", async () => { @@ -250,7 +291,6 @@ describe("DepositBoxERC721WithMetadata", () => { describe("tests for `postMessage` function", async () => { let erc721: ERC721OnChain; let erc721OnChain: ERC721OnChain; - let messages: MessagesTester; let weiAmount: string; let sign: { blsSignature: [BigNumber, BigNumber], @@ -263,7 +303,6 @@ describe("DepositBoxERC721WithMetadata", () => { weiAmount = 1e18.toString(); erc721 = await deployERC721OnChain("ERC721", "ERC721"); erc721OnChain = await deployERC721OnChain("ERC721OnChain", "ERC721OnChain"); - messages = await deployMessages(); sign = { blsSignature: BlsSignature, @@ -368,7 +407,6 @@ describe("DepositBoxERC721WithMetadata", () => { const tokenId = 10; const tokenURI = "Hello10"; const to = user.address; - const schainHash = stringValue(web3.utils.soliditySha3(schainName)); const zeroHash = "0x0000000000000000000000000000000000000000000000000000000000000000"; const senderFromSchain = deployer.address; diff --git a/proxy/test/DepositBoxEth.ts b/proxy/test/DepositBoxEth.ts index 9c491f6a7..f4e0c60bc 100644 --- a/proxy/test/DepositBoxEth.ts +++ b/proxy/test/DepositBoxEth.ts @@ -114,8 +114,10 @@ describe("DepositBoxEth", () => { let messageProxy: MessageProxyForMainnet; let linker: Linker; let communityPool: CommunityPool; + let messages: MessagesTester; const contractManagerAddress = "0x0000000000000000000000000000000000000000"; const schainName = "Schain"; + const schainHash = stringValue(web3.utils.soliditySha3(schainName)); before(async () => { [deployer, user, user2, richGuy] = await ethers.getSigners(); @@ -135,6 +137,7 @@ describe("DepositBoxEth", () => { linker = await deployLinker(contractManager, messageProxy); depositBoxEth = await deployDepositBoxEth(contractManager, linker, messageProxy); communityPool = await deployCommunityPool(contractManager, linker, messageProxy); + messages = await deployMessages(); await messageProxy.grantRole(await messageProxy.CHAIN_CONNECTOR_ROLE(), linker.address); await messageProxy.grantRole(await messageProxy.EXTRA_CONTRACT_REGISTRAR_ROLE(), deployer.address); await initializeSchain(contractManager, schainName, user.address, 1, 1); @@ -198,6 +201,30 @@ describe("DepositBoxEth", () => { expect(lockAndDataBalance).to.equal(wei); }); + it("should invoke `depositDirect` without mistakes", async () => { + // preparation + // the wei should be MORE than (55000 * 1000000000) + // GAS_AMOUNT_POST_MESSAGE * AVERAGE_TX_PRICE constants in DepositBox.sol + // to avoid the `Not enough money` error + const wei = "20000000000000000"; + // add schain to avoid the `Unconnected chain` error + await linker + .connect(deployer) + .connectSchain(schainName, [deployer.address, deployer.address, deployer.address]); + + const data = await messages.encodeTransferEthMessage(user.address, wei); + // execution + await depositBoxEth + .connect(deployer) + .depositDirect(schainName, user.address, { value: wei }) + .should.emit(messageProxy, "OutgoingMessage") + .withArgs(schainHash, 0, depositBoxEth.address, deployer.address, data); + + const lockAndDataBalance = await web3.eth.getBalance(depositBoxEth.address); + // expectation + expect(lockAndDataBalance).to.equal(wei); + }); + it("should revert `Not allowed. in DepositBox`", async () => { // preparation const error = "Use deposit function"; @@ -230,12 +257,10 @@ describe("DepositBoxEth", () => { describe("tests for `postMessage` function", async () => { let erc20: ERC20OnChain; let erc20Clone: ERC20OnChain; - let messages: MessagesTester; beforeEach(async () => { erc20 = await deployERC20OnChain("D2-token", "D2",); erc20Clone = await deployERC20OnChain("Token", "T",); - messages = await deployMessages(); }); it("should rejected with `Sender is not a MessageProxy`", async () => { @@ -296,7 +321,7 @@ describe("DepositBoxEth", () => { }); it("should rejected with message `Not enough money to finish this transaction` when " - + "`sender != ILockAndDataDB(lockAndDataAddress).tokenManagerAddresses(schainHash)`", async () => { + + "`sender != DepositBoxEth.tokenManagerAddresses(schainHash)`", async () => { // preparation const error = "Not enough money to finish this transaction"; const wei = 1e18.toString(); @@ -437,7 +462,6 @@ describe("DepositBoxEth", () => { const senderFromSchain = deployer.address; const wei = "30000000000000000"; const bytesData = await messages.encodeTransferEthMessage(user.address, wei); - const schainHash = stringValue(web3.utils.soliditySha3(schainName)); await setCommonPublicKey(contractManager, schainName); @@ -487,7 +511,6 @@ describe("DepositBoxEth", () => { const senderFromSchain = deployer.address; const wei = "30000000000000000"; const bytesData = await messages.encodeTransferEthMessage(user.address, wei); - const schainHash = stringValue(web3.utils.soliditySha3(schainName)); await setCommonPublicKey(contractManager, schainName); @@ -561,7 +584,6 @@ describe("DepositBoxEth", () => { const senderFromSchain = deployer.address; const wei = "30000000000000000"; - const schainHash = stringValue(web3.utils.soliditySha3(schainName)); const fallbackEthTester = await deployFallbackEthTester(depositBoxEth, communityPool, schainName); const bytesData = await messages.encodeTransferEthMessage(fallbackEthTester.address, wei); diff --git a/proxy/test/MessageProxy.ts b/proxy/test/MessageProxy.ts index 6d613f821..2ac1670b4 100644 --- a/proxy/test/MessageProxy.ts +++ b/proxy/test/MessageProxy.ts @@ -41,7 +41,6 @@ import { SchainsInternal } from "../typechain/"; import { stringToHex, getPublicKey } from "./utils/helper"; -import ABIReceiverMock = require("../artifacts/contracts/test/ReceiverMock.sol/ReceiverMock.json"); import { deployLinker } from "./utils/deploy/mainnet/linker"; import { deployMessageProxyForMainnet } from "./utils/deploy/mainnet/messageProxyForMainnet"; import { deployDepositBoxEth } from "./utils/deploy/mainnet/depositBoxEth"; @@ -52,15 +51,14 @@ import { setCommonPublicKey } from "./utils/skale-manager-utils/keyStorage"; import { deployMessageProxyCaller } from "./utils/deploy/test/messageProxyCaller"; import { deployMessages } from "./utils/deploy/messages"; import { deployKeyStorageMock } from "./utils/deploy/test/keyStorageMock"; -import { ethers, web3 } from "hardhat"; +import { ethers } from "hardhat"; import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/dist/src/signer-with-address"; import { BigNumber, Wallet } from "ethers"; -import { assert, expect } from "chai"; +import { expect } from "chai"; import { MessageProxyForSchainTester } from "../typechain/MessageProxyForSchainTester"; import { deployMessageProxyForSchainTester } from "./utils/deploy/test/messageProxyForSchainTester"; import { deployCommunityPool } from "./utils/deploy/mainnet/communityPool"; import { createNode } from "./utils/skale-manager-utils/nodes"; -import { skipTime } from "./utils/time"; chai.should(); chai.use((chaiAsPromised)); @@ -1668,6 +1666,11 @@ describe("MessageProxy", () => { }); }); + it("should not allow anyone to top up balance with sFuel", async () => { + await messageProxyForSchain.connect(user).topUpReceiverBalance(user.address) + .should.be.rejectedWith("Sender is not registered"); + }); + describe("register and remove extra contracts", async () => { it("should register extra contract", async () => { const fakeContractOnSchain = deployer.address; diff --git a/proxy/test/TokenManagerERC1155.ts b/proxy/test/TokenManagerERC1155.ts index 5343ae63a..e634d620c 100644 --- a/proxy/test/TokenManagerERC1155.ts +++ b/proxy/test/TokenManagerERC1155.ts @@ -216,6 +216,7 @@ describe("TokenManagerERC1155", () => { tokenManagerERC11552 = await deployTokenManagerERC1155(newSchainName, messageProxyForSchain2.address, tokenManagerLinker2, communityLocker2, fakeDepositBox); await erc1155OnTargetChain.connect(deployer).grantRole(await erc1155OnTargetChain.MINTER_ROLE(), tokenManagerERC11552.address); await tokenManagerLinker2.registerTokenManager(tokenManagerERC11552.address); + await messageProxyForSchain2.registerExtraContractForAll(tokenManagerERC11552.address); }); it("should invoke `transferToSchainERC1155` without mistakes", async () => { @@ -624,13 +625,6 @@ describe("TokenManagerERC1155", () => { await targetErc1155OnChain.connect(user).setApprovalForAll(tokenManagerERC11552.address, true); - await tokenManagerERC11552 - .connect(user) - .transferToSchainERC1155(schainName, erc1155OnOriginChain.address, id, amount) - .should.be.eventually.rejectedWith("Sender contract is not registered"); - - await messageProxyForSchain2.registerExtraContract(schainName, tokenManagerERC11552.address); - await tokenManagerERC11552 .connect(user) .transferToSchainERC1155(schainName, erc1155OnOriginChain.address, id, amount); @@ -716,13 +710,6 @@ describe("TokenManagerERC1155", () => { await erc1155OnTargetChain.connect(user).setApprovalForAll(tokenManagerERC11552.address, true); - await tokenManagerERC11552 - .connect(user) - .transferToSchainERC1155(schainName, erc1155OnOriginChain.address, id, amount) - .should.be.eventually.rejectedWith("Sender contract is not registered"); - - await messageProxyForSchain2.registerExtraContract(schainName, tokenManagerERC11552.address); - await tokenManagerERC11552 .connect(user) .transferToSchainERC1155(schainName, erc1155OnOriginChain.address, id, amount); @@ -813,13 +800,6 @@ describe("TokenManagerERC1155", () => { await targetErc1155OnChain.connect(user).setApprovalForAll(tokenManagerERC11552.address, true); - await tokenManagerERC11552 - .connect(user) - .transferToSchainERC1155(schainName, erc1155OnOriginChain.address, id, amount) - .should.be.eventually.rejectedWith("Sender contract is not registered"); - - await messageProxyForSchain2.registerExtraContract(schainName, tokenManagerERC11552.address); - await tokenManagerERC11552 .connect(user) .transferToSchainERC1155(schainName, erc1155OnOriginChain.address, id, amount); @@ -973,13 +953,6 @@ describe("TokenManagerERC1155", () => { await erc1155OnTargetChain.connect(user).setApprovalForAll(tokenManagerERC11552.address, true); - await tokenManagerERC11552 - .connect(user) - .transferToSchainERC1155(schainName, erc1155OnOriginChain.address, id, amount) - .should.be.eventually.rejectedWith("Sender contract is not registered"); - - await messageProxyForSchain2.registerExtraContract(schainName, tokenManagerERC11552.address); - await tokenManagerERC11552 .connect(user) .transferToSchainERC1155(schainName, erc1155OnOriginChain.address, id, amount); @@ -1066,8 +1039,6 @@ describe("TokenManagerERC1155", () => { }); it("should not be able to transfer X->Y->Z", async () => { - // await messageProxyForSchain.registerExtraContract(newSchainName, tokenManagerERC1155.address); - // add connected chain: await messageProxyForSchain.connect(deployer).grantRole(await messageProxyForSchain.CHAIN_CONNECTOR_ROLE(), deployer.address); await messageProxyForSchain.connect(deployer).addConnectedChain(newSchainName); @@ -1129,7 +1100,6 @@ describe("TokenManagerERC1155", () => { await messageProxyForSchain2.connect(deployer).grantRole(await messageProxyForSchain2.CHAIN_CONNECTOR_ROLE(), deployer.address); await messageProxyForSchain2.connect(deployer).addConnectedChain(newSchainNameZ); - await messageProxyForSchain2.registerExtraContract(newSchainNameZ, tokenManagerERC11552.address); await tokenManagerERC11552.addTokenManager(newSchainNameZ, tokenManagerERC1155Z.address); await erc1155OnTargetChain.connect(user).setApprovalForAll(tokenManagerERC11552.address, true); @@ -1146,8 +1116,6 @@ describe("TokenManagerERC1155", () => { }); it("should not be able to transfer main chain token or clone to mainnet", async () => { - // await messageProxyForSchain.registerExtraContract(newSchainName, tokenManagerERC1155.address); - // add connected chain: await messageProxyForSchain.connect(deployer).grantRole(await messageProxyForSchain.CHAIN_CONNECTOR_ROLE(), deployer.address); await messageProxyForSchain.connect(deployer).addConnectedChain(newSchainName); @@ -1205,8 +1173,6 @@ describe("TokenManagerERC1155", () => { .exitToMainERC1155(erc1155OnTargetChain.address, id, amount) .should.be.eventually.rejectedWith("Incorrect main chain token"); - await messageProxyForSchain2.registerExtraContract(schainName, tokenManagerERC11552.address); - await tokenManagerERC11552 .connect(user) .transferToSchainERC1155(schainName, erc1155OnOriginChain.address, id, amount); @@ -1258,6 +1224,7 @@ describe("TokenManagerERC1155", () => { tokenManagerERC11552 = await deployTokenManagerERC1155(newSchainName, messageProxyForSchain2.address, tokenManagerLinker2, communityLocker2, fakeDepositBox); await erc1155OnTargetChain.connect(deployer).grantRole(await erc1155OnTargetChain.MINTER_ROLE(), tokenManagerERC11552.address); await tokenManagerLinker2.registerTokenManager(tokenManagerERC11552.address); + await messageProxyForSchain2.registerExtraContractForAll(tokenManagerERC11552.address); }); it("should invoke `transferToSchainERC1155` without mistakes", async () => { @@ -1699,13 +1666,6 @@ describe("TokenManagerERC1155", () => { await targetErc1155OnChain.connect(user).setApprovalForAll(tokenManagerERC11552.address, true); - await tokenManagerERC11552 - .connect(user) - .transferToSchainERC1155Batch(schainName, erc1155OnOriginChain.address, ids, amounts) - .should.be.eventually.rejectedWith("Sender contract is not registered"); - - await messageProxyForSchain2.registerExtraContract(schainName, tokenManagerERC11552.address); - await tokenManagerERC11552 .connect(user) .transferToSchainERC1155Batch(schainName, erc1155OnOriginChain.address, ids, amounts); @@ -1796,13 +1756,6 @@ describe("TokenManagerERC1155", () => { await erc1155OnTargetChain.connect(user).setApprovalForAll(tokenManagerERC11552.address, true); - await tokenManagerERC11552 - .connect(user) - .transferToSchainERC1155Batch(schainName, erc1155OnOriginChain.address, ids, amounts) - .should.be.eventually.rejectedWith("Sender contract is not registered"); - - await messageProxyForSchain2.registerExtraContract(schainName, tokenManagerERC11552.address); - await tokenManagerERC11552 .connect(user) .transferToSchainERC1155Batch(schainName, erc1155OnOriginChain.address, ids, amounts); @@ -1905,13 +1858,6 @@ describe("TokenManagerERC1155", () => { await targetErc1155OnChain.connect(user).setApprovalForAll(tokenManagerERC11552.address, true); - await tokenManagerERC11552 - .connect(user) - .transferToSchainERC1155Batch(schainName, erc1155OnOriginChain.address, ids, amounts) - .should.be.eventually.rejectedWith("Sender contract is not registered"); - - await messageProxyForSchain2.registerExtraContract(schainName, tokenManagerERC11552.address); - await tokenManagerERC11552 .connect(user) .transferToSchainERC1155Batch(schainName, erc1155OnOriginChain.address, ids, amounts); @@ -2092,13 +2038,6 @@ describe("TokenManagerERC1155", () => { await erc1155OnTargetChain.connect(user).setApprovalForAll(tokenManagerERC11552.address, true); - await tokenManagerERC11552 - .connect(user) - .transferToSchainERC1155Batch(schainName, erc1155OnOriginChain.address, ids, amounts) - .should.be.eventually.rejectedWith("Sender contract is not registered"); - - await messageProxyForSchain2.registerExtraContract(schainName, tokenManagerERC11552.address); - await tokenManagerERC11552 .connect(user) .transferToSchainERC1155Batch(schainName, erc1155OnOriginChain.address, ids, amounts); @@ -2212,8 +2151,6 @@ describe("TokenManagerERC1155", () => { }); it("should not be able to transfer X->Y->Z", async () => { - // await messageProxyForSchain.registerExtraContract(newSchainName, tokenManagerERC1155.address); - // add connected chain: await messageProxyForSchain.connect(deployer).grantRole(await messageProxyForSchain.CHAIN_CONNECTOR_ROLE(), deployer.address); await messageProxyForSchain.connect(deployer).addConnectedChain(newSchainName); @@ -2280,7 +2217,6 @@ describe("TokenManagerERC1155", () => { await messageProxyForSchain2.connect(deployer).grantRole(await messageProxyForSchain2.CHAIN_CONNECTOR_ROLE(), deployer.address); await messageProxyForSchain2.connect(deployer).addConnectedChain(newSchainNameZ); - await messageProxyForSchain2.registerExtraContract(newSchainNameZ, tokenManagerERC11552.address); await tokenManagerERC11552.addTokenManager(newSchainNameZ, tokenManagerERC1155Z.address); await erc1155OnTargetChain.connect(user).setApprovalForAll(tokenManagerERC11552.address, true); @@ -2297,8 +2233,6 @@ describe("TokenManagerERC1155", () => { }); it("should not be able to transfer main chain token or clone to mainnet", async () => { - // await messageProxyForSchain.registerExtraContract(newSchainName, tokenManagerERC1155.address); - // add connected chain: await messageProxyForSchain.connect(deployer).grantRole(await messageProxyForSchain.CHAIN_CONNECTOR_ROLE(), deployer.address); await messageProxyForSchain.connect(deployer).addConnectedChain(newSchainName); @@ -2361,8 +2295,6 @@ describe("TokenManagerERC1155", () => { .exitToMainERC1155Batch(erc1155OnTargetChain.address, ids, amounts) .should.be.eventually.rejectedWith("Incorrect main chain token"); - await messageProxyForSchain2.registerExtraContract(schainName, tokenManagerERC11552.address); - await tokenManagerERC11552 .connect(user) .transferToSchainERC1155Batch(schainName, erc1155OnOriginChain.address, ids, amounts); diff --git a/proxy/test/TokenManagerERC20.ts b/proxy/test/TokenManagerERC20.ts index f432e5dfa..7cc74b06f 100644 --- a/proxy/test/TokenManagerERC20.ts +++ b/proxy/test/TokenManagerERC20.ts @@ -31,10 +31,10 @@ import { TokenManagerERC20, TokenManagerLinker, MessageProxyForSchainTester, - CommunityLocker + CommunityLocker, + EtherbaseMock } from "../typechain"; -import { stringValue } from "./utils/helper"; chai.should(); chai.use((chaiAsPromised as any)); @@ -46,7 +46,7 @@ import { deployTokenManagerLinker } from "./utils/deploy/schain/tokenManagerLink import { deployMessages } from "./utils/deploy/messages"; import { deployCommunityLocker } from "./utils/deploy/schain/communityLocker"; -import { ethers, web3 } from "hardhat"; +import { ethers } from "hardhat"; import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/dist/src/signer-with-address"; import { BigNumber } from "ethers"; @@ -61,8 +61,8 @@ describe("TokenManagerERC20", () => { const mainnetName = "Mainnet"; const schainName = "D2-chain"; - const schainId = stringValue(web3.utils.soliditySha3(schainName)); - const mainnetId = stringValue(web3.utils.soliditySha3("Mainnet")); + const schainId = ethers.utils.solidityKeccak256(["string"], [schainName]); + const mainnetId = ethers.utils.solidityKeccak256(["string"], ["Mainnet"]); let fakeDepositBox: string; let fakeCommunityPool: any; let erc20OnChain: ERC20OnChain; @@ -134,6 +134,8 @@ describe("TokenManagerERC20", () => { const data2 = await messages.encodeTransferErc20AndTokenInfoMessage(erc20OnMainnet.address, to, amount, totalSupply, { name, symbol, decimals: 18 }); await tokenManagerErc20.connect(schainOwner).enableAutomaticDeploy(); + await messageProxyForSchain.registerExtraContractForAll(tokenManagerErc20.address); + // execution const res = await (await messageProxyForSchain.postMessage(tokenManagerErc20.address, mainnetId, fakeDepositBox, data)).wait(); @@ -143,7 +145,7 @@ describe("TokenManagerERC20", () => { assert("No events were emitted"); } else { newAddress = "0x" + res.events[res.events.length - 1].topics[3].slice(-40); - const newERC20Contract = await (await ethers.getContractFactory("ERC20OnChain")).attach(newAddress) as ERC20OnChain; + const newERC20Contract = (await ethers.getContractFactory("ERC20OnChain")).attach(newAddress) as ERC20OnChain; let balance = await newERC20Contract.functions.balanceOf(to); parseInt(balance.toString(), 10).should.be.equal(amount); // expectation @@ -256,7 +258,7 @@ describe("TokenManagerERC20", () => { let tokenManagerErc202: TokenManagerERC20; let communityLocker2: CommunityLocker; const newSchainName = "NewChain"; - const newSchainId = stringValue(web3.utils.soliditySha3(newSchainName)); + const newSchainId = ethers.utils.solidityKeccak256(["string"], [newSchainName]); beforeEach(async () => { erc20OnOriginChain = await deployERC20OnChain("NewToken", "NTN"); @@ -305,7 +307,7 @@ describe("TokenManagerERC20", () => { outgoingMessagesCounter.should.be.deep.equal(BigNumber.from(1)); }); - it("should reject `transferToSchainERC20` when executing earlier then allowed", async () => { + it("should reject `transferToSchainERC20` when executing earlier than allowed", async () => { const amount = "20000000000000000"; await messageProxyForSchain.registerExtraContract(newSchainName, tokenManagerErc20.address); @@ -460,18 +462,20 @@ describe("TokenManagerERC20", () => { await messageProxyForSchain2.postMessage(tokenManagerErc202.address, schainId, tokenManagerErc20.address, data).should.be.eventually.rejectedWith("Automatic deploy is disabled"); await tokenManagerErc202.enableAutomaticDeploy(); + await messageProxyForSchain2.registerExtraContractForAll(tokenManagerErc202.address); await messageProxyForSchain2.postMessage(tokenManagerErc202.address, schainId, tokenManagerErc20.address, data); const addressERC20OnSchain = await tokenManagerErc202.clonesErc20(schainId, erc20OnOriginChain.address); - const targetErc20OnChain = await (await ethers.getContractFactory("ERC20OnChain")).attach(addressERC20OnSchain) as ERC20OnChain; + const targetErc20OnChain = (await ethers.getContractFactory("ERC20OnChain")).attach(addressERC20OnSchain) as ERC20OnChain; expect((await targetErc20OnChain.functions.balanceOf(user.address)).toString()).to.be.equal(amount); }); - it("should invoke `transferToSchainERC20` and receive tokens without mistakes double", async () => { + it("should invoke `transferToSchainERC20` and receive tokens without mistakes back and forward twice", async () => { const amount = "20000000000000000"; await messageProxyForSchain.registerExtraContract(newSchainName, tokenManagerErc20.address); + await messageProxyForSchain2.registerExtraContractForAll(tokenManagerErc202.address); // add connected chain: await messageProxyForSchain.connect(deployer).grantRole(await messageProxyForSchain.CHAIN_CONNECTOR_ROLE(), deployer.address); @@ -527,7 +531,7 @@ describe("TokenManagerERC20", () => { await messageProxyForSchain2.postMessage(tokenManagerErc202.address, schainId, tokenManagerErc20.address, data); const addressERC20OnSchain = await tokenManagerErc202.clonesErc20(schainId, erc20OnOriginChain.address); - const targetErc20OnChain = await (await ethers.getContractFactory("ERC20OnChain")).attach(addressERC20OnSchain) as ERC20OnChain; + const targetErc20OnChain = (await ethers.getContractFactory("ERC20OnChain")).attach(addressERC20OnSchain) as ERC20OnChain; expect((await targetErc20OnChain.functions.balanceOf(user.address)).toString()).to.be.equal(amount); const amount2 = "50000000000000000"; @@ -557,6 +561,7 @@ describe("TokenManagerERC20", () => { it("should invoke `transferToSchainERC20` and receive tokens without mistakes double with attached token", async () => { const amount = "20000000000000000"; await messageProxyForSchain.registerExtraContract(newSchainName, tokenManagerErc20.address); + await messageProxyForSchain2.registerExtraContractForAll(tokenManagerErc202.address); // add connected chain: await messageProxyForSchain.connect(deployer).grantRole(await messageProxyForSchain.CHAIN_CONNECTOR_ROLE(), deployer.address); @@ -640,7 +645,8 @@ describe("TokenManagerERC20", () => { it("should invoke `transferToSchainERC20` and transfer back without mistakes", async () => { const amount = "20000000000000000"; - await messageProxyForSchain.registerExtraContract(newSchainName, tokenManagerErc20.address); + await messageProxyForSchain.registerExtraContractForAll(tokenManagerErc20.address); + await messageProxyForSchain2.registerExtraContractForAll(tokenManagerErc202.address); // add connected chain: await messageProxyForSchain.connect(deployer).grantRole(await messageProxyForSchain.CHAIN_CONNECTOR_ROLE(), deployer.address); @@ -696,7 +702,7 @@ describe("TokenManagerERC20", () => { await messageProxyForSchain2.postMessage(tokenManagerErc202.address, schainId, tokenManagerErc20.address, data); const addressERC20OnSchain = await tokenManagerErc202.clonesErc20(schainId, erc20OnOriginChain.address); - const targetErc20OnChain = await (await ethers.getContractFactory("ERC20OnChain")).attach(addressERC20OnSchain) as ERC20OnChain; + const targetErc20OnChain = (await ethers.getContractFactory("ERC20OnChain")).attach(addressERC20OnSchain) as ERC20OnChain; expect((await targetErc20OnChain.functions.balanceOf(user.address)).toString()).to.be.equal(amount); await tokenManagerErc202 @@ -716,13 +722,6 @@ describe("TokenManagerERC20", () => { await targetErc20OnChain.connect(user).approve(tokenManagerErc202.address, amount); - await tokenManagerErc202 - .connect(user) - .transferToSchainERC20(schainName, erc20OnOriginChain.address, amount) - .should.be.eventually.rejectedWith("Sender contract is not registered"); - - await messageProxyForSchain2.registerExtraContract(schainName, tokenManagerErc202.address); - await tokenManagerErc202 .connect(user) .transferToSchainERC20(schainName, erc20OnOriginChain.address, amount); @@ -740,7 +739,8 @@ describe("TokenManagerERC20", () => { it("should invoke `transferToSchainERC20` and transfer back without mistakes with attached tokens", async () => { const amount = "20000000000000000"; - await messageProxyForSchain.registerExtraContract(newSchainName, tokenManagerErc20.address); + await messageProxyForSchain.registerExtraContractForAll(tokenManagerErc20.address); + await messageProxyForSchain2.registerExtraContractForAll(tokenManagerErc202.address); // add connected chain: await messageProxyForSchain.connect(deployer).grantRole(await messageProxyForSchain.CHAIN_CONNECTOR_ROLE(), deployer.address); @@ -811,13 +811,6 @@ describe("TokenManagerERC20", () => { await erc20OnTargetChain.connect(user).approve(tokenManagerErc202.address, amount); - await tokenManagerErc202 - .connect(user) - .transferToSchainERC20(schainName, erc20OnOriginChain.address, amount) - .should.be.eventually.rejectedWith("Sender contract is not registered"); - - await messageProxyForSchain2.registerExtraContract(schainName, tokenManagerErc202.address); - await tokenManagerErc202 .connect(user) .transferToSchainERC20(schainName, erc20OnOriginChain.address, amount); @@ -836,7 +829,8 @@ describe("TokenManagerERC20", () => { it("should invoke `transferToSchainERC20` and transfer back without mistakes double", async () => { const amount = "20000000000000000"; - await messageProxyForSchain.registerExtraContract(newSchainName, tokenManagerErc20.address); + await messageProxyForSchain.registerExtraContractForAll(tokenManagerErc20.address); + await messageProxyForSchain2.registerExtraContractForAll(tokenManagerErc202.address); // add connected chain: await messageProxyForSchain.connect(deployer).grantRole(await messageProxyForSchain.CHAIN_CONNECTOR_ROLE(), deployer.address); @@ -892,7 +886,7 @@ describe("TokenManagerERC20", () => { await messageProxyForSchain2.postMessage(tokenManagerErc202.address, schainId, tokenManagerErc20.address, data); const addressERC20OnSchain = await tokenManagerErc202.clonesErc20(schainId, erc20OnOriginChain.address); - const targetErc20OnChain = await (await ethers.getContractFactory("ERC20OnChain")).attach(addressERC20OnSchain) as ERC20OnChain; + const targetErc20OnChain = (await ethers.getContractFactory("ERC20OnChain")).attach(addressERC20OnSchain) as ERC20OnChain; expect((await targetErc20OnChain.functions.balanceOf(user.address)).toString()).to.be.equal(amount); await tokenManagerErc202 @@ -912,13 +906,6 @@ describe("TokenManagerERC20", () => { await targetErc20OnChain.connect(user).approve(tokenManagerErc202.address, amount); - await tokenManagerErc202 - .connect(user) - .transferToSchainERC20(schainName, erc20OnOriginChain.address, amount) - .should.be.eventually.rejectedWith("Sender contract is not registered"); - - await messageProxyForSchain2.registerExtraContract(schainName, tokenManagerErc202.address); - await tokenManagerErc202 .connect(user) .transferToSchainERC20(schainName, erc20OnOriginChain.address, amount); @@ -1006,7 +993,8 @@ describe("TokenManagerERC20", () => { it("should invoke `transferToSchainERC20` and transfer back without mistakes double with attached tokens", async () => { const amount = "20000000000000000"; - await messageProxyForSchain.registerExtraContract(newSchainName, tokenManagerErc20.address); + await messageProxyForSchain.registerExtraContractForAll(tokenManagerErc20.address); + await messageProxyForSchain2.registerExtraContractForAll(tokenManagerErc202.address); // add connected chain: await messageProxyForSchain.connect(deployer).grantRole(await messageProxyForSchain.CHAIN_CONNECTOR_ROLE(), deployer.address); @@ -1077,13 +1065,6 @@ describe("TokenManagerERC20", () => { await erc20OnTargetChain.connect(user).approve(tokenManagerErc202.address, amount); - await tokenManagerErc202 - .connect(user) - .transferToSchainERC20(schainName, erc20OnOriginChain.address, amount) - .should.be.eventually.rejectedWith("Sender contract is not registered"); - - await messageProxyForSchain2.registerExtraContract(schainName, tokenManagerErc202.address); - await tokenManagerErc202 .connect(user) .transferToSchainERC20(schainName, erc20OnOriginChain.address, amount); @@ -1211,6 +1192,7 @@ describe("TokenManagerERC20", () => { await tokenManagerErc202.connect(deployer).grantRole(await tokenManagerErc202.TOKEN_REGISTRAR_ROLE(), schainOwner.address); await tokenManagerErc202.connect(schainOwner).addERC20TokenByOwner(schainName, erc20OnOriginChain.address, erc20OnTargetChain.address); + await messageProxyForSchain2.registerExtraContractForAll(tokenManagerErc202.address); await messageProxyForSchain2.postMessage(tokenManagerErc202.address, schainId, tokenManagerErc20.address, data); @@ -1236,7 +1218,6 @@ describe("TokenManagerERC20", () => { await messageProxyForSchain2.connect(deployer).grantRole(await messageProxyForSchain2.CHAIN_CONNECTOR_ROLE(), deployer.address); await messageProxyForSchain2.connect(deployer).addConnectedChain(newSchainNameZ); - await messageProxyForSchain2.registerExtraContract(newSchainNameZ, tokenManagerErc202.address); await tokenManagerErc202.addTokenManager(newSchainNameZ, tokenManagerErc20Z.address); await erc20OnTargetChain.connect(user).approve(tokenManagerErc202.address, amount); @@ -1254,7 +1235,8 @@ describe("TokenManagerERC20", () => { it("should not be able to transfer main chain token or clone to mainnet", async () => { const amount = "20000000000000000"; - await messageProxyForSchain.registerExtraContract(newSchainName, tokenManagerErc20.address); + await messageProxyForSchain.registerExtraContractForAll(tokenManagerErc20.address); + await messageProxyForSchain2.registerExtraContractForAll(tokenManagerErc202.address); // add connected chain: await messageProxyForSchain.connect(deployer).grantRole(await messageProxyForSchain.CHAIN_CONNECTOR_ROLE(), deployer.address); @@ -1315,7 +1297,6 @@ describe("TokenManagerERC20", () => { .exitToMainERC20(erc20OnTargetChain.address, amount) .should.be.eventually.rejectedWith("Incorrect main chain token"); - await messageProxyForSchain2.registerExtraContract(schainName, tokenManagerErc202.address); await tokenManagerErc202 .connect(user) @@ -1332,8 +1313,6 @@ describe("TokenManagerERC20", () => { await erc20OnOriginChain.connect(user).approve(tokenManagerErc20.address, amount); - await messageProxyForSchain.registerExtraContract("Mainnet", tokenManagerErc20.address); - await tokenManagerErc20 .connect(user) .exitToMainERC20(erc20OnOriginChain.address, amount) @@ -1349,13 +1328,17 @@ describe("TokenManagerERC20", () => { }); describe("tests for `postMessage` function", async () => { + beforeEach(async () => { + await messageProxyForSchain.registerExtraContractForAll(tokenManagerErc20.address); + }); + it("should transfer ERC20 token with token info", async () => { // preparation const amount = 10; const to = user.address; const remoteTokenManagerAddress = fakeDepositBox; const fromSchainName = "fromSchainName"; - const fromSchainHash = stringValue(web3.utils.soliditySha3(fromSchainName)); + const fromSchainHash = ethers.utils.solidityKeccak256(["string"], [fromSchainName]); await tokenManagerErc20.addTokenManager(fromSchainName, remoteTokenManagerAddress); // await tokenManagerErc20.connect(schainOwner).addERC20TokenByOwner(mainnetName, erc20OnMainnet.address, erc20OnChain.address); @@ -1377,7 +1360,7 @@ describe("TokenManagerERC20", () => { await messageProxyForSchain.postMessage(tokenManagerErc20.address, fromSchainHash, remoteTokenManagerAddress, data); // expectation const addressERC20OnSchain = await tokenManagerErc20.clonesErc20(fromSchainHash, erc20OnMainnet.address); - const targetErc20OnChain = await (await ethers.getContractFactory("ERC20OnChain")).attach(addressERC20OnSchain) as ERC20OnChain; + const targetErc20OnChain = (await ethers.getContractFactory("ERC20OnChain")).attach(addressERC20OnSchain) as ERC20OnChain; expect(parseInt((await targetErc20OnChain.functions.balanceOf(to)).toString(), 10)) .to.be.equal(amount); }); @@ -1386,7 +1369,7 @@ describe("TokenManagerERC20", () => { // preparation const remoteTokenManagerAddress = fakeDepositBox; const fromSchainName = "fromSchainName"; - const fromSchainHash = stringValue(web3.utils.soliditySha3(fromSchainName)); + const fromSchainHash = ethers.utils.solidityKeccak256(["string"], [fromSchainName]); await messageProxyForSchain.connect(deployer).addConnectedChain(fromSchainName); await tokenManagerErc20.addTokenManager(fromSchainName, remoteTokenManagerAddress); await tokenManagerErc20.connect(schainOwner).addERC20TokenByOwner(fromSchainName, erc20OnMainnet.address, erc20OnChain.address); @@ -1406,16 +1389,16 @@ describe("TokenManagerERC20", () => { await messageProxyForSchain.postMessage(tokenManagerErc20.address, fromSchainHash, remoteTokenManagerAddress, data); // expectation const addressERC20OnSchain = await tokenManagerErc20.clonesErc20(fromSchainHash, erc20OnMainnet.address); - const targetErc20OnChain = await (await ethers.getContractFactory("ERC20OnChain")).attach(addressERC20OnSchain) as ERC20OnChain; + const targetErc20OnChain = (await ethers.getContractFactory("ERC20OnChain")).attach(addressERC20OnSchain) as ERC20OnChain; expect(parseInt((await targetErc20OnChain.functions.balanceOf(to)).toString(), 10)) .to.be.equal(amount); }); - it("should should transfer token to schain and automaticaly deploy", async () => { + it("should should transfer token to schain and automatically deploy", async () => { // preparation const remoteTokenManagerAddress = fakeDepositBox; const fromSchainName = "fromSchainName"; - const fromSchainHash = stringValue(web3.utils.soliditySha3(fromSchainName)); + const fromSchainHash = ethers.utils.solidityKeccak256(["string"], [fromSchainName]); await tokenManagerErc20.addTokenManager(fromSchainName, remoteTokenManagerAddress); const amount = 10; @@ -1443,7 +1426,7 @@ describe("TokenManagerERC20", () => { // expectation const addressERC20OnSchain = await tokenManagerErc20.clonesErc20(fromSchainHash, erc20OnMainnet.address); - const targetErc20OnChain = await (await ethers.getContractFactory("ERC20OnChain")).attach(addressERC20OnSchain) as ERC20OnChain; + const targetErc20OnChain = (await ethers.getContractFactory("ERC20OnChain")).attach(addressERC20OnSchain) as ERC20OnChain; expect(parseInt((await targetErc20OnChain.functions.balanceOf(to)).toString(), 10)) .to.be.equal(amount); }); @@ -1464,7 +1447,7 @@ describe("TokenManagerERC20", () => { const to = user.address; const remoteTokenManagerAddress = fakeDepositBox; const fromSchainName = "fromSchainName"; - const fromSchainHash = stringValue(web3.utils.soliditySha3(fromSchainName)); + const fromSchainHash = ethers.utils.solidityKeccak256(["string"], [fromSchainName]); await tokenManagerErc20.addTokenManager(fromSchainName, remoteTokenManagerAddress); await tokenManagerErc20.connect(schainOwner).addERC20TokenByOwner(mainnetName, erc20OnMainnet.address, erc20OnChain.address); @@ -1495,5 +1478,53 @@ describe("TokenManagerERC20", () => { await messageProxyForSchain.postMessage(tokenManagerErc20.address, mainnetId, fakeDepositBox, data) .should.be.eventually.rejectedWith("Total supply exceeded"); }); + + it("should top up a receiver", async () => { + const amount = 10; + const receiver = ethers.Wallet.createRandom().connect(ethers.provider); + const remoteTokenManager = ethers.Wallet.createRandom(); + const sourceSchainName = "sourceSchain"; + const sourceSchainHash = ethers.utils.solidityKeccak256(["string"], [sourceSchainName]) + await tokenManagerErc20.addTokenManager(sourceSchainName, remoteTokenManager.address); + const etherbase = await (await ethers.getContractFactory("EtherbaseMock")).deploy() as EtherbaseMock; + await etherbase.initialize(deployer.address); + await etherbase.grantRole(await etherbase.ETHER_MANAGER_ROLE(), messageProxyForSchain.address); + await messageProxyForSchain.setEtherbase(etherbase.address); + await deployer.sendTransaction({to: etherbase.address, value: ethers.utils.parseEther("3")}); + + (await receiver.getBalance()).should.be.equal(0); + + const data = await messages.encodeTransferErc20AndTokenInfoMessage( + erc20OnMainnet.address, + receiver.address, + amount, + 2 * amount, + { + name: await erc20OnMainnet.name(), + symbol: await erc20OnMainnet.symbol(), + decimals: await erc20OnMainnet.decimals() + } + ); + await tokenManagerErc20.connect(schainOwner).enableAutomaticDeploy(); + await messageProxyForSchain.postMessage( + tokenManagerErc20.address, + sourceSchainHash, + remoteTokenManager.address, + data); + + (await receiver.getBalance()).should.be.equal(0); + + await expect(messageProxyForSchain.setMinimumReceiverBalance(ethers.utils.parseEther("2"))) + .to.emit(messageProxyForSchain, 'MinimumReceiverBalanceChanged') + .withArgs(0, ethers.utils.parseEther("2")); + + await messageProxyForSchain.postMessage( + tokenManagerErc20.address, + sourceSchainHash, + remoteTokenManager.address, + data); + + (await receiver.getBalance()).should.be.equal(await messageProxyForSchain.minimumReceiverBalance()); + }) }); }); diff --git a/proxy/test/TokenManagerERC721.ts b/proxy/test/TokenManagerERC721.ts index 9072679a9..29bf4d2a9 100644 --- a/proxy/test/TokenManagerERC721.ts +++ b/proxy/test/TokenManagerERC721.ts @@ -225,6 +225,7 @@ describe("TokenManagerERC721", () => { tokenManagerERC7212 = await deployTokenManagerERC721(newSchainName, messageProxyForSchain2.address, tokenManagerLinker2, communityLocker2, fakeDepositBox); await erc721OnTargetChain.connect(deployer).grantRole(await erc721OnTargetChain.MINTER_ROLE(), tokenManagerERC7212.address); await tokenManagerLinker2.registerTokenManager(tokenManagerERC7212.address); + await messageProxyForSchain2.registerExtraContractForAll(tokenManagerERC7212.address); }); it("should invoke `transferToSchainERC721` without mistakes", async () => { @@ -580,7 +581,7 @@ describe("TokenManagerERC721", () => { }); it("should invoke `transferToSchainERC721` and transfer back without mistakes", async () => { - await messageProxyForSchain.registerExtraContract(newSchainName, tokenManagerERC721.address); + await messageProxyForSchain.registerExtraContractForAll(tokenManagerERC721.address); // add connected chain: await messageProxyForSchain.connect(deployer).grantRole(await messageProxyForSchain.CHAIN_CONNECTOR_ROLE(), deployer.address); @@ -654,13 +655,6 @@ describe("TokenManagerERC721", () => { await targetErc721OnChain.connect(user).approve(tokenManagerERC7212.address, tokenId); - await tokenManagerERC7212 - .connect(user) - .transferToSchainERC721(schainName, erc721OnOriginChain.address, tokenId) - .should.be.eventually.rejectedWith("Sender contract is not registered"); - - await messageProxyForSchain2.registerExtraContract(schainName, tokenManagerERC7212.address); - await tokenManagerERC7212 .connect(user) .transferToSchainERC721(schainName, erc721OnOriginChain.address, tokenId); @@ -677,7 +671,7 @@ describe("TokenManagerERC721", () => { }); it("should invoke `transferToSchainERC721` and transfer back without mistakes with attached tokens", async () => { - await messageProxyForSchain.registerExtraContract(newSchainName, tokenManagerERC721.address); + await messageProxyForSchain.registerExtraContractForAll(tokenManagerERC721.address); // add connected chain: await messageProxyForSchain.connect(deployer).grantRole(await messageProxyForSchain.CHAIN_CONNECTOR_ROLE(), deployer.address); @@ -746,13 +740,6 @@ describe("TokenManagerERC721", () => { await erc721OnTargetChain.connect(user).approve(tokenManagerERC7212.address, tokenId); - await tokenManagerERC7212 - .connect(user) - .transferToSchainERC721(schainName, erc721OnOriginChain.address, tokenId) - .should.be.eventually.rejectedWith("Sender contract is not registered"); - - await messageProxyForSchain2.registerExtraContract(schainName, tokenManagerERC7212.address); - await tokenManagerERC7212 .connect(user) .transferToSchainERC721(schainName, erc721OnOriginChain.address, tokenId); @@ -770,7 +757,7 @@ describe("TokenManagerERC721", () => { it("should invoke `transferToSchainERC721` and transfer back without mistakes double", async () => { - await messageProxyForSchain.registerExtraContract(newSchainName, tokenManagerERC721.address); + await messageProxyForSchain.registerExtraContractForAll(tokenManagerERC721.address); // add connected chain: await messageProxyForSchain.connect(deployer).grantRole(await messageProxyForSchain.CHAIN_CONNECTOR_ROLE(), deployer.address); @@ -844,13 +831,6 @@ describe("TokenManagerERC721", () => { await targetErc721OnChain.connect(user).approve(tokenManagerERC7212.address, tokenId); - await tokenManagerERC7212 - .connect(user) - .transferToSchainERC721(schainName, erc721OnOriginChain.address, tokenId) - .should.be.eventually.rejectedWith("Sender contract is not registered"); - - await messageProxyForSchain2.registerExtraContract(schainName, tokenManagerERC7212.address); - await tokenManagerERC7212 .connect(user) .transferToSchainERC721(schainName, erc721OnOriginChain.address, tokenId); @@ -935,7 +915,7 @@ describe("TokenManagerERC721", () => { }); it("should invoke `transferToSchainERC721` and transfer back without mistakes double with attached tokens", async () => { - await messageProxyForSchain.registerExtraContract(newSchainName, tokenManagerERC721.address); + await messageProxyForSchain.registerExtraContractForAll(tokenManagerERC721.address); // add connected chain: await messageProxyForSchain.connect(deployer).grantRole(await messageProxyForSchain.CHAIN_CONNECTOR_ROLE(), deployer.address); @@ -1004,13 +984,6 @@ describe("TokenManagerERC721", () => { await erc721OnTargetChain.connect(user).approve(tokenManagerERC7212.address, tokenId); - await tokenManagerERC7212 - .connect(user) - .transferToSchainERC721(schainName, erc721OnOriginChain.address, tokenId) - .should.be.eventually.rejectedWith("Sender contract is not registered"); - - await messageProxyForSchain2.registerExtraContract(schainName, tokenManagerERC7212.address); - await tokenManagerERC7212 .connect(user) .transferToSchainERC721(schainName, erc721OnOriginChain.address, tokenId); @@ -1157,7 +1130,6 @@ describe("TokenManagerERC721", () => { await messageProxyForSchain2.connect(deployer).grantRole(await messageProxyForSchain2.CHAIN_CONNECTOR_ROLE(), deployer.address); await messageProxyForSchain2.connect(deployer).addConnectedChain(newSchainNameZ); - await messageProxyForSchain2.registerExtraContract(newSchainNameZ, tokenManagerERC7212.address); await tokenManagerERC7212.addTokenManager(newSchainNameZ, tokenManagerERC721Z.address); await erc721OnTargetChain.connect(user).approve(tokenManagerERC7212.address, tokenId); @@ -1174,7 +1146,7 @@ describe("TokenManagerERC721", () => { }); it("should not be able to transfer main chain token or clone to mainnet", async () => { - await messageProxyForSchain.registerExtraContract(newSchainName, tokenManagerERC721.address); + await messageProxyForSchain.registerExtraContractForAll(tokenManagerERC721.address); // add connected chain: await messageProxyForSchain.connect(deployer).grantRole(await messageProxyForSchain.CHAIN_CONNECTOR_ROLE(), deployer.address); @@ -1233,8 +1205,6 @@ describe("TokenManagerERC721", () => { .exitToMainERC721(erc721OnTargetChain.address, tokenId) .should.be.eventually.rejectedWith("Incorrect main chain token"); - await messageProxyForSchain2.registerExtraContract(schainName, tokenManagerERC7212.address); - await tokenManagerERC7212 .connect(user) .transferToSchainERC721(schainName, erc721OnOriginChain.address, tokenId); @@ -1250,8 +1220,6 @@ describe("TokenManagerERC721", () => { await erc721OnOriginChain.connect(user).approve(tokenManagerERC721.address, tokenId); - await messageProxyForSchain.registerExtraContract("Mainnet", tokenManagerERC721.address); - await tokenManagerERC721 .connect(user) .exitToMainERC721(erc721OnOriginChain.address, tokenId) @@ -1267,6 +1235,9 @@ describe("TokenManagerERC721", () => { }); describe("tests for `postMessage` function", async () => { + beforeEach(async () => { + await messageProxyForSchain.registerExtraContractForAll(tokenManagerERC721.address); + }); it("should transfer ERC721 token token with token info", async () => { // preparation diff --git a/proxy/test/TokenManagerERC721WithMetadata.ts b/proxy/test/TokenManagerERC721WithMetadata.ts index b85757697..163f5689c 100644 --- a/proxy/test/TokenManagerERC721WithMetadata.ts +++ b/proxy/test/TokenManagerERC721WithMetadata.ts @@ -230,6 +230,7 @@ describe("TokenManagerERC721WithMetadata", () => { tokenManagerERC721WithMetadata2 = await deployTokenManagerERC721WithMetadata(newSchainName, messageProxyForSchain2.address, tokenManagerLinker2, communityLocker2, fakeDepositBox); await erc721OnTargetChain.connect(deployer).grantRole(await erc721OnTargetChain.MINTER_ROLE(), tokenManagerERC721WithMetadata2.address); await tokenManagerLinker2.registerTokenManager(tokenManagerERC721WithMetadata2.address); + await messageProxyForSchain2.registerExtraContractForAll(tokenManagerERC721WithMetadata2.address); }); it("should invoke `transferToSchainERC721` without mistakes", async () => { @@ -605,7 +606,7 @@ describe("TokenManagerERC721WithMetadata", () => { }); it("should invoke `transferToSchainERC721` and transfer back without mistakes", async () => { - await messageProxyForSchain.registerExtraContract(newSchainName, tokenManagerERC721WithMetadata.address); + await messageProxyForSchain.registerExtraContractForAll(tokenManagerERC721WithMetadata.address); // add connected chain: await messageProxyForSchain.connect(deployer).grantRole(await messageProxyForSchain.CHAIN_CONNECTOR_ROLE(), deployer.address); @@ -682,13 +683,6 @@ describe("TokenManagerERC721WithMetadata", () => { await targetErc721OnChain.connect(user).approve(tokenManagerERC721WithMetadata2.address, tokenId); - await tokenManagerERC721WithMetadata2 - .connect(user) - .transferToSchainERC721(schainName, erc721OnOriginChain.address, tokenId) - .should.be.eventually.rejectedWith("Sender contract is not registered"); - - await messageProxyForSchain2.registerExtraContract(schainName, tokenManagerERC721WithMetadata2.address); - await tokenManagerERC721WithMetadata2 .connect(user) .transferToSchainERC721(schainName, erc721OnOriginChain.address, tokenId); @@ -707,7 +701,7 @@ describe("TokenManagerERC721WithMetadata", () => { }); it("should invoke `transferToSchainERC721` and transfer back without mistakes with attached tokens", async () => { - await messageProxyForSchain.registerExtraContract(newSchainName, tokenManagerERC721WithMetadata.address); + await messageProxyForSchain.registerExtraContractForAll(tokenManagerERC721WithMetadata.address); // add connected chain: await messageProxyForSchain.connect(deployer).grantRole(await messageProxyForSchain.CHAIN_CONNECTOR_ROLE(), deployer.address); @@ -778,13 +772,6 @@ describe("TokenManagerERC721WithMetadata", () => { await erc721OnTargetChain.connect(user).approve(tokenManagerERC721WithMetadata2.address, tokenId); - await tokenManagerERC721WithMetadata2 - .connect(user) - .transferToSchainERC721(schainName, erc721OnOriginChain.address, tokenId) - .should.be.eventually.rejectedWith("Sender contract is not registered"); - - await messageProxyForSchain2.registerExtraContract(schainName, tokenManagerERC721WithMetadata2.address); - await tokenManagerERC721WithMetadata2 .connect(user) .transferToSchainERC721(schainName, erc721OnOriginChain.address, tokenId); @@ -804,7 +791,7 @@ describe("TokenManagerERC721WithMetadata", () => { it("should invoke `transferToSchainERC721` and transfer back without mistakes double", async () => { - await messageProxyForSchain.registerExtraContract(newSchainName, tokenManagerERC721WithMetadata.address); + await messageProxyForSchain.registerExtraContractForAll(tokenManagerERC721WithMetadata.address); // add connected chain: await messageProxyForSchain.connect(deployer).grantRole(await messageProxyForSchain.CHAIN_CONNECTOR_ROLE(), deployer.address); @@ -881,13 +868,6 @@ describe("TokenManagerERC721WithMetadata", () => { await targetErc721OnChain.connect(user).approve(tokenManagerERC721WithMetadata2.address, tokenId); - await tokenManagerERC721WithMetadata2 - .connect(user) - .transferToSchainERC721(schainName, erc721OnOriginChain.address, tokenId) - .should.be.eventually.rejectedWith("Sender contract is not registered"); - - await messageProxyForSchain2.registerExtraContract(schainName, tokenManagerERC721WithMetadata2.address); - await tokenManagerERC721WithMetadata2 .connect(user) .transferToSchainERC721(schainName, erc721OnOriginChain.address, tokenId); @@ -986,7 +966,7 @@ describe("TokenManagerERC721WithMetadata", () => { }); it("should invoke `transferToSchainERC721` and transfer back without mistakes double with attached tokens", async () => { - await messageProxyForSchain.registerExtraContract(newSchainName, tokenManagerERC721WithMetadata.address); + await messageProxyForSchain.registerExtraContractForAll(tokenManagerERC721WithMetadata.address); // add connected chain: await messageProxyForSchain.connect(deployer).grantRole(await messageProxyForSchain.CHAIN_CONNECTOR_ROLE(), deployer.address); @@ -1057,13 +1037,6 @@ describe("TokenManagerERC721WithMetadata", () => { await erc721OnTargetChain.connect(user).approve(tokenManagerERC721WithMetadata2.address, tokenId); - await tokenManagerERC721WithMetadata2 - .connect(user) - .transferToSchainERC721(schainName, erc721OnOriginChain.address, tokenId) - .should.be.eventually.rejectedWith("Sender contract is not registered"); - - await messageProxyForSchain2.registerExtraContract(schainName, tokenManagerERC721WithMetadata2.address); - await tokenManagerERC721WithMetadata2 .connect(user) .transferToSchainERC721(schainName, erc721OnOriginChain.address, tokenId); @@ -1227,7 +1200,6 @@ describe("TokenManagerERC721WithMetadata", () => { await messageProxyForSchain2.connect(deployer).grantRole(await messageProxyForSchain2.CHAIN_CONNECTOR_ROLE(), deployer.address); await messageProxyForSchain2.connect(deployer).addConnectedChain(newSchainNameZ); - await messageProxyForSchain2.registerExtraContract(newSchainNameZ, tokenManagerERC721WithMetadata2.address); await tokenManagerERC721WithMetadata2.addTokenManager(newSchainNameZ, tokenManagerERC721WithMetadataZ.address); await erc721OnTargetChain.connect(user).approve(tokenManagerERC721WithMetadata2.address, tokenId); @@ -1244,7 +1216,7 @@ describe("TokenManagerERC721WithMetadata", () => { }); it("should not be able to transfer main chain token or clone to mainnet", async () => { - await messageProxyForSchain.registerExtraContract(newSchainName, tokenManagerERC721WithMetadata.address); + await messageProxyForSchain.registerExtraContractForAll(tokenManagerERC721WithMetadata.address); // add connected chain: await messageProxyForSchain.connect(deployer).grantRole(await messageProxyForSchain.CHAIN_CONNECTOR_ROLE(), deployer.address); @@ -1306,8 +1278,6 @@ describe("TokenManagerERC721WithMetadata", () => { .exitToMainERC721(erc721OnTargetChain.address, tokenId) .should.be.eventually.rejectedWith("Incorrect main chain token"); - await messageProxyForSchain2.registerExtraContract(schainName, tokenManagerERC721WithMetadata2.address); - await tokenManagerERC721WithMetadata2 .connect(user) .transferToSchainERC721(schainName, erc721OnOriginChain.address, tokenId); @@ -1325,8 +1295,6 @@ describe("TokenManagerERC721WithMetadata", () => { await erc721OnOriginChain.connect(user).approve(tokenManagerERC721WithMetadata.address, tokenId); - await messageProxyForSchain.registerExtraContract("Mainnet", tokenManagerERC721WithMetadata.address); - await tokenManagerERC721WithMetadata .connect(user) .exitToMainERC721(erc721OnOriginChain.address, tokenId) @@ -1342,6 +1310,9 @@ describe("TokenManagerERC721WithMetadata", () => { }); describe("tests for `postMessage` function", async () => { + beforeEach(async () => { + await messageProxyForSchain.registerExtraContractForAll(tokenManagerERC721WithMetadata.address); + }); it("should transfer ERC721 token token with token info", async () => { // preparation diff --git a/proxy/test/TokenManagerEth.ts b/proxy/test/TokenManagerEth.ts index 5c09e35e8..edf174fb2 100644 --- a/proxy/test/TokenManagerEth.ts +++ b/proxy/test/TokenManagerEth.ts @@ -66,8 +66,8 @@ describe("TokenManagerEth", () => { let messages: MessagesTester; let ethERC20: EthErc20; let communityLocker: CommunityLocker; - let fakeDepositBox: any; - let fakeCommunityPool: any; + let fakeDepositBox: string; + let fakeCommunityPool: string; const mainnetHash = stringValue(web3.utils.soliditySha3("Mainnet")); before(async () => { @@ -277,6 +277,7 @@ describe("TokenManagerEth", () => { it("should transfer eth", async () => { // preparation + await messageProxyForSchain.registerExtraContractForAll(tokenManagerEth.address); const fromSchainName = "fromSchainName"; const fromSchainId = stringValue(web3.utils.soliditySha3(fromSchainName)); const amount = "10"; @@ -284,9 +285,7 @@ describe("TokenManagerEth", () => { const to = user.address; // for transfer eth bytesData should be equal `0x01`. See the `.fallbackOperationTypeConvert` function const bytesData = await messages.encodeTransferEthMessage(to, amount); - // redeploy tokenManagerEth with `developer` address instead `messageProxyForSchain.address` - // to avoid `Not a sender` error - tokenManagerEth = await deployTokenManagerEth(schainName, deployer.address, tokenManagerLinker, communityLocker, fakeDepositBox, ethERC20.address); + // add schain to avoid the `Receiver chain is incorrect` error await tokenManagerEth .connect(deployer) @@ -294,19 +293,26 @@ describe("TokenManagerEth", () => { await ethERC20.connect(deployer).grantRole(await ethERC20.MINTER_ROLE(), tokenManagerEth.address); await ethERC20.connect(deployer).grantRole(await ethERC20.BURNER_ROLE(), tokenManagerEth.address); // execution - await tokenManagerEth - .connect(deployer) - .postMessage(fromSchainId, sender, bytesData) - .should.be.eventually.rejectedWith("Receiver chain is incorrect"); - - await tokenManagerEth - .connect(deployer) - .postMessage(mainnetHash, sender, bytesData) - .should.be.eventually.rejectedWith("Receiver chain is incorrect"); - - await tokenManagerEth - .connect(deployer) - .postMessage(mainnetHash, fakeDepositBox, bytesData); + await messageProxyForSchain.postMessage( + tokenManagerEth.address, + fromSchainId, + sender, + bytesData + ).should.be.eventually.rejectedWith("Receiver chain is incorrect"); + + await messageProxyForSchain.postMessage( + tokenManagerEth.address, + mainnetHash, + sender, + bytesData + ).should.be.eventually.rejectedWith("Receiver chain is incorrect"); + + await messageProxyForSchain.postMessage( + tokenManagerEth.address, + mainnetHash, + fakeDepositBox, + bytesData + ); // expectation expect(parseInt((BigNumber.from(await ethERC20.balanceOf(to))).toString(), 10)) .to.be.equal(parseInt(amount, 10)); diff --git a/proxy/yarn.lock b/proxy/yarn.lock index a7c087d95..5d37506cc 100644 --- a/proxy/yarn.lock +++ b/proxy/yarn.lock @@ -762,10 +762,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.1.0-develop.0": - version "1.1.0-develop.0" - resolved "https://registry.yarnpkg.com/@skalenetwork/ima-interfaces/-/ima-interfaces-1.1.0-develop.0.tgz#a91a794affee2138e03c779f9f32cd34652a47b7" - integrity sha512-wy1DYbsgccYETqgayxyHh9Dh8+q13F0JrDCpHn7nodwnjxp95cAtjyD9KTN4Y4/Ix/pr5rFqQjBXtXQas36uBg== +"@skalenetwork/ima-interfaces@^2.0.0-beta.0": + version "2.0.0-develop.0" + resolved "https://registry.yarnpkg.com/@skalenetwork/ima-interfaces/-/ima-interfaces-2.0.0-develop.0.tgz#2db130e63278f7a00bd848a4f2e10dda61e353fb" + integrity sha512-vSDY3vcuuUUBDMM3fifU++HPl2W9c2VSjkFK68r5Hc1Sc0VMYWcdfpx9yRwvp5NKY/B78+k80661GJHn+vuCCQ== dependencies: "@skalenetwork/skale-manager-interfaces" "^0.1.2"