Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support of IMA on SKALE chains #50

Merged
merged 4 commits into from
Mar 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion dictionary
2 changes: 2 additions & 0 deletions python/setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ packages = find:
include_package_data = True
python_requires = >=3.9
install_requires =
parver
semver
web3 >= 6, < 7

[options.packages.find]
Expand Down
1 change: 1 addition & 0 deletions python/src/skale_contracts/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
REPOSITORY_URL = 'https://skalenetwork.github.io/skale-contracts/'
METADATA_FILENAME = 'metadata.json'
NETWORK_TIMEOUT = 60
PREDEPLOYED_ALIAS = 'predeployed'
23 changes: 20 additions & 3 deletions python/src/skale_contracts/instance.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import json
from typing import TYPE_CHECKING, Optional
from attr import dataclass
from parver import Version as PyVersion
from semver.version import Version as SemVersion


if TYPE_CHECKING:
Expand Down Expand Up @@ -53,9 +55,24 @@ def web3(self) -> Web3:
def version(self) -> str:
"""Get version of the project instance"""
if self._version is None:
self._version = self._get_version()
if not '-' in self._version:
self._version = self._version + '-stable.0'
raw_version = self._get_version()
if SemVersion.is_valid(raw_version):
sem_version = SemVersion.parse(raw_version)
if sem_version.prerelease is None:
sem_version = sem_version.replace(prerelease='stable.0')
self._version = str(sem_version)
else:
py_version = PyVersion.parse(raw_version)
sem_version = SemVersion(*py_version.release)
if py_version.pre_tag == 'a':
sem_version = sem_version.replace(
prerelease=f'develop.{py_version.pre}'
)
elif py_version.pre_tag == 'b':
sem_version = sem_version.replace(
prerelease=f'beta.{py_version.pre}'
)
self._version = str(sem_version)
return self._version

@property
Expand Down
3 changes: 3 additions & 0 deletions python/src/skale_contracts/project_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class Projects:
"""Contains all known projects"""
skale_manager = ProjectMetadata(name='skale-manager', path='skale-manager')
mainnet_ima = ProjectMetadata(name='mainnet-ima', path='mainnet-ima')
schain_ima = ProjectMetadata(name='schain-ima', path='schain-ima')


def create_project(network: Network, name: str) -> Project:
Expand All @@ -25,4 +26,6 @@ def create_project(network: Network, name: str) -> Project:
return projects.SkaleManager(network, Projects.skale_manager)
if name == Projects.mainnet_ima.name:
return projects.MainnetIma(network, Projects.mainnet_ima)
if name == Projects.schain_ima.name:
return projects.SchainIma(network, Projects.schain_ima)
raise ValueError(f'Project with name {name} is unknown')
6 changes: 4 additions & 2 deletions python/src/skale_contracts/projects/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
"""Supported projects"""
from .ima import MainnetImaProject as MainnetIma
from .ima import \
MainnetImaProject as MainnetIma, \
SchainImaProject as SchainIma
from .skale_manager import SkaleManagerProject as SkaleManager

__all__ = ["MainnetIma", "SkaleManager"]
__all__ = ['MainnetIma', 'SchainIma', 'SkaleManager']
52 changes: 44 additions & 8 deletions python/src/skale_contracts/projects/ima.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
from __future__ import annotations
from typing import cast, TYPE_CHECKING
from eth_typing import Address
from eth_utils.address import to_canonical_address

from skale_contracts.constants import PREDEPLOYED_ALIAS
from skale_contracts.instance import Instance, DEFAULT_GET_VERSION_FUNCTION
from skale_contracts.project import Project

Expand Down Expand Up @@ -47,17 +49,14 @@ def get_contract_address(self, name: str) -> Address:
if name == 'MessageProxyForMainnet':
return self.address
if name == 'CommunityPool':
return cast(
Address,
return to_canonical_address(
self.get_contract("MessageProxyForMainnet").functions.communityPool().call()
)
if name == 'Linker':
return cast(
Address,
return to_canonical_address(
self.get_contract("MessageProxyForMainnet").functions.linker().call()
)
return cast(
Address,
return to_canonical_address(
self.contract_manager.functions.getContract(name).call()
)

Expand All @@ -66,8 +65,7 @@ def contract_manager(self) -> Contract:
"""ContractManager contract of a skale-manager instance associated with the IMA"""
if self._contract_manager is None:
self._contract_manager = self.web3.eth.contract(
address=cast(
Address,
address=to_canonical_address(
self.get_contract("MessageProxyForMainnet")
.functions.contractManagerOfSkaleManager().call()
),
Expand All @@ -84,3 +82,41 @@ def create_instance(self, address: Address) -> Instance:

def get_abi_filename(self, version: str) -> str:
return f'mainnet-ima-{version}-abi.json'


class SchainImaInstance(ImaInstance):
"""Represents IMA instance on schain"""

PREDEPLOYED: dict[str, Address] = {
name: to_canonical_address(address) for name, address in {
'ProxyAdmin': '0xd2aAa00000000000000000000000000000000000',
'MessageProxyForSchain': '0xd2AAa00100000000000000000000000000000000',
'KeyStorage': '0xd2aaa00200000000000000000000000000000000',
'CommunityLocker': '0xD2aaa00300000000000000000000000000000000',
'TokenManagerEth': '0xd2AaA00400000000000000000000000000000000',
'TokenManagerERC20': '0xD2aAA00500000000000000000000000000000000',
'TokenManagerERC721': '0xD2aaa00600000000000000000000000000000000',
'TokenManagerLinker': '0xD2aAA00800000000000000000000000000000000',
'TokenManagerERC1155': '0xD2aaA00900000000000000000000000000000000',
'TokenManagerERC721WithMetadata': '0xd2AaA00a00000000000000000000000000000000'
}.items()}

def get_contract_address(self, name: str) -> Address:
if name in self.PREDEPLOYED:
return self.PREDEPLOYED[name]
raise RuntimeError(f"Can't get address of {name} contract")


class SchainImaProject(ImaProject):
"""Represents schain part of IMA project"""

def get_instance(self, alias_or_address: str) -> Instance:
if alias_or_address == PREDEPLOYED_ALIAS:
return self.create_instance(SchainImaInstance.PREDEPLOYED['MessageProxyForSchain'])
return super().get_instance(alias_or_address)

def create_instance(self, address: Address) -> Instance:
return SchainImaInstance(self, address)

def get_abi_filename(self, version: str) -> str:
return f'schain-ima-{version}-abi.json'
4 changes: 2 additions & 2 deletions python/src/skale_contracts/projects/skale_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from __future__ import annotations
from typing import cast, TYPE_CHECKING
from eth_utils.address import to_canonical_address

from skale_contracts.instance import Instance, DEFAULT_GET_VERSION_FUNCTION
from skale_contracts.project import Project
Expand Down Expand Up @@ -48,8 +49,7 @@ def __init__(self, project: Project, address: Address) -> None:
}

def get_contract_address(self, name: str) -> Address:
return cast(
Address,
return to_canonical_address(
self.contract_manager.functions.getContract(self._actual_name(name)).call()
)

Expand Down
Loading