From 1af4a9f1b458c55d3c6fc99db5d3d4e55a09663f Mon Sep 17 00:00:00 2001 From: lilixac Date: Mon, 5 Oct 2020 16:09:53 +0545 Subject: [PATCH 1/7] Implementation of IRC16 token library --- ODIContracts/tokens/IRC16/IIRC16.py | 76 +++++ ODIContracts/tokens/IRC16/IRC16.py | 275 ++++++++++++++++++ ODIContracts/tokens/IRC16/IRC16Capped.py | 24 ++ .../tokens/IRC16/IRC16Controllable.py | 26 ++ ODIContracts/tokens/IRC16/IRC16Pausable.py | 29 ++ 5 files changed, 430 insertions(+) create mode 100644 ODIContracts/tokens/IRC16/IIRC16.py create mode 100644 ODIContracts/tokens/IRC16/IRC16.py create mode 100644 ODIContracts/tokens/IRC16/IRC16Capped.py create mode 100644 ODIContracts/tokens/IRC16/IRC16Controllable.py create mode 100644 ODIContracts/tokens/IRC16/IRC16Pausable.py diff --git a/ODIContracts/tokens/IRC16/IIRC16.py b/ODIContracts/tokens/IRC16/IIRC16.py new file mode 100644 index 0000000..7a6797e --- /dev/null +++ b/ODIContracts/tokens/IRC16/IIRC16.py @@ -0,0 +1,76 @@ +from iconservice import * + +TAG = 'SampleToken' + + +# An interface of ICON Token Standard, IRC-16 +class TokenStandard(ABC): + ''' + Normal token methods + ''' + @abstractmethod + def name(self) -> str: + pass + + @abstractmethod + def symbol(self) -> str: + pass + + @abstractmethod + def decimals(self) -> int: + pass + + @abstractmethod + def totalSupply(self) -> int: + pass + + @abstractmethod + def balanceOf(self, _owner: Address) -> int: + pass + + @abstractmethod + def transfer(self, _to: Address, _value: int, _data: bytes = None): + pass + + ''' + Partitions + ''' + @abstractmethod + def balanceOfByPartition(self, _partition: str, _owner: Address) -> int: + pass + + @abstractmethod + def partitionsOf(self, _owner: Address) -> dict: + pass + + @abstractmethod + def getDocument(self, _name: str) -> dict: + pass + + @abstractmethod + def setDocument(self, _name: str, _uri: str, _document_hash: str) -> None: + pass + + @abstractmethod + def transferByPartition(self, _partition: str, _to: Address, _amount: int, _data: bytes = None) -> None: + pass + + @abstractmethod + def operatorTransferByPartition(self, _partition: str, _from: Address, _to: Address, _amount: int, _data: bytes = None) -> None: + pass + + @abstractmethod + def authorizeOperator(self, _operator: Address) -> None: + pass + + @abstractmethod + def revokeOperator(self, _operator: Address) -> None: + pass + + @abstractmethod + def authorizeOperatorForPartition(self, _partition: str, _operator: Address) -> None: + pass + + @abstractmethod + def revokeOperatorForPartition(self, _partition: str, _operator: Address) -> None: + pass \ No newline at end of file diff --git a/ODIContracts/tokens/IRC16/IRC16.py b/ODIContracts/tokens/IRC16/IRC16.py new file mode 100644 index 0000000..6f72efb --- /dev/null +++ b/ODIContracts/tokens/IRC16/IRC16.py @@ -0,0 +1,275 @@ +from iconservice import * +from .IIRC16 import TokenStandard +from ...utils.consts import * +from ...utils.pausable import * + +TAG = 'IRC16' + +class IRC16(IconScoreBase): + + _NAME = 'name' + _SYMBOL = 'symbol' + _DECIMALS = 'decimals' + _TOTAL_SUPPLY = 'total_supply' + _BALANCES = 'balances' + _ALLOWANCES = 'allowances' + _PAUSED = 'paused' + _CAP = 'cap' + _CONTROLLABLE = "controllable" + _CONTROLLERS = "controllers" + _IS_CONTROLLER = "is_controller" + _PARTITIONS = 'partitions' + _APPROVALS = "approvals" + _PARTITION_APPROVALS = "partition_approvals" + _DOCUMENT = 'document' + _ZERO_ADDRESS = Address.from_prefix_and_int(AddressPrefix.EOA, 0) + + def __init__(self, db: IconScoreDatabase) -> None: + super().__init__(db) + self._name = VarDB(self._NAME, db, value_type=str) + self._symbol = VarDB(self._SYMBOL, db, value_type=str) + self._decimals = VarDB(self._DECIMALS, db, value_type=int) + self._total_supply = VarDB(self._TOTAL_SUPPLY, db, value_type=int) + self._balances = DictDB(self._BALANCES, db, value_type=int) + self._paused = VarDB(self._PAUSED, db, value_type=bool) + self._cap = VarDB(self._CAP, db, value_type=int) + self._controllable = VarDB(self._CONTROLLABLE, db, value_type=bool) + self._is_controller = DictDB(self._IS_CONTROLLER, db, value_type=bool) + self._controllers = ArrayDB(self._CONTROLLERS,db, value_type=Address) + self._partitions = DictDB(self._PARTITIONS, db, value_type=int, depth=2) + self._document = DictDB(self._DOCUMENT, db, value_type=str, depth=2) + self._approvals = DictDB(self._APPROVALS, db, value_type=bool, depth = 2) + self._partition_approvals = DictDB(self._PARTITION_APPROVALS, db, value_type=bool, depth = 3) + + def on_install(self, _name:str, _symbol:str, _initialSupply:int, _decimals:int, _paused: bool = False, _cap: int = DEFAULT_CAP_VALUE, _controllable: bool = True) -> None: + super().on_install() + if (len(_symbol) <= 0): + revert("Invalid Symbol name") + if (len(_name) <= 0): + revert("Invalid Token Name") + if _initialSupply <= 0: + revert("Initial Supply cannot be less than zero") + if _decimals < 0: + revert("Decimals cannot be less than zero") + if _cap <= 0: + revert("Cap value cannot be less than zero") + if _cap < _initialSupply: + revert("Cap value cannot be less than initial supply") + total_supply = _initialSupply * 10 ** _decimals + + self._name.set(_name) + self._symbol.set(_symbol) + self._decimals.set(_decimals) + self._total_supply.set(total_supply) + self._cap.set(_cap) + self._paused.set(_paused) + + self._controllable.set(_controllable) + self._controllers.put(self.owner) + + def on_update(self) -> None: + super().on_update() + + # Eventlogs + @eventlog(indexed=2) + def TransferByPartition(self, _partition: str, _operator: Address, _from: Address, _to: Address, _amount: int, _data: bytes): + pass + + @eventlog(indexed=3) + def IssueByPartition(self, _partition: str, _to: Address, _amount: int, _data: bytes): + pass + + @eventlog(indexed=3) + def RedeemByPartition(self, _partition: str, _operator: Address, _owner: Address, _amount: int, _data: bytes): + pass + + @eventlog(indexed=2) + def AuthorizeOperator(self, _operator: Address, _sender: Address): + pass + + @eventlog(indexed=2) + def RevokeOperator(self, _operator: Address, _sender: Address): + pass + + @eventlog(indexed=3) + def AuthorizeOperatorForPartition(self, _owner: Address, _partition: str, _operator: Address): + pass + + @eventlog(indexed=3) + def RevokeOperatorForPartition(self, _owner: Address, _partition: str, _operator: Address): + pass + + @eventlog(indexed=3) + def SetDocument(self, _name: str, _uri: str, _document_hash: str): + pass + + @external(readonly=True) + def name(self) -> str: + return self._name.get() + + @external(readonly=True) + def symbol(self) -> str: + return self._symbol.get() + + @external(readonly=True) + def decimals(self) -> int: + return self._decimals.get() + + @external(readonly=True) + def totalSupply(self) -> int: + return self._total_supply.get() + + @external(readonly=True) + def balanceOf(self, _owner: Address) -> int: + return self._balances[_owner] + + @external(readonly=True) + def balanceOfByPartition(self, _partition: str, _owner: Address) -> int: + return self._partitions[_owner][_partition] + + # @external(readonly=True) + # def partitionsOf(self, _owner: Address) -> DictDB: + # return self._partitions[_owner] + + @external(readonly=True) + def getDocument(self, _name:str) -> dict: + doc = {} + doc = { + "name" : _name, + "uri" : self._document[_name]['uri'], + "document_hash" : self._document[_name]['document_hash'], + } + return doc + + @external + def setDocument(self, _name: str, _uri: str, _document_hash: str) -> None: + if (self.msg.sender != self.owner): + revert("Only self.owner has permission to set document.") + self._document[_name]['uri'] = _uri + self._document[_name]['document_hash'] = _document_hash + self.SetDocument(_name, _uri, _document_hash) + + @external(readonly=True) + @whenNotPaused + def canTransferByPartition(self, _partition: str, _to: Address, _amount: int, _data: bytes = None) -> str: + if _to == self._ZERO_ADDRESS: + revert("ZERO ADDRESS: Invalid Recieving Address") + elif self._partitions[_from][_partition] < _amount: + revert("Insufficient partition balance.") + elif self._balances[_from] < _amount: + revert("Insufficient balance.") + elif not self._partitions[_from][_partition]: + revert("Invalid partition") + + return "Transfer can be successful." + + @external + def transferByPartition(self, _partition: str, _to: Address, _amount: int, _data: bytes = None) -> None: + self._transferByPartition(_partition, self.msg.sender,self.msg.sender, _to, _amount, _data) + + @external + def operatorTransferByPartition(self, _partition: str, _from: Address, _to: Address, _amount: int, _data: bytes = None) -> None: + if self.isOperatorForPartition(_partition, self.msg.sender, _from) or self.isOperator(self.msg.sender, _from): + self._transferByPartition(_partition, self.msg.sender, _from, _to, _amount, _data) + else: + revert(f"{self.msg.sender} is not a operator.") + + def _transferByPartition(self, _partition: str,_operator: Address, _from: Address, _to: Address, _amount: int, _data:bytes = None) -> None: + if self._partitions[_from][_partition] < _amount: + revert("Insufficient partition balance.") + if self._balances[_from] < _amount: + revert("Insufficient balance.") + + self._beforeTokenTransfer(_from, _to, _amount) + + self._partitions[_from][_partition] -= _amount + self._balances[_from] -= _amount + self._partitions[_to][_partition] += _amount + self._balances[_to] += _amount + self.TransferByPartition(_partition, _operator, _from, _to, _amount, _data) + + @external + def authorizeOperator(self, _operator: Address) -> None: + if self._approvals[self.msg.sender][_operator]: + revert(f"{_operator} is already a operator.") + self._approvals[self.msg.sender][_operator] = True + self.AuthorizeOperator(_operator, self.msg.sender) + + @external + def revokeOperator(self, _operator: Address) -> None: + if not self._approvals[self.msg.sender][_operator]: + revert(f"{_operator} is not a operator.") + self._approvals[self.msg.sender][_operator] = False + self.RevokeOperator(_operator, self.msg.sender) + + @external + def authorizeOperatorForPartition(self, _partition: str, _operator: Address) -> None: + if self._partition_approvals[self.msg.sender][_partition][_operator]: + revert(f"{_operator} is already a operator for {_partition} partition.") + self._partition_approvals[self.msg.sender][_partition][_operator] = True + self.AuthorizeOperatorForPartition(self.msg.sender, _partition, _operator) + + @external + def revokeOperatorForPartition(self, _partition: str, _operator: Address) -> None: + if not self._partition_approvals[self.msg.sender][_partition][_operator]: + revert(f"{_operator} is already not a operator for {_partition} partition.") + self._partition_approvals[self.msg.sender][_partition][_operator] = False + self.AuthorizeOperatorForPartition(self.msg.sender, _partition, _operator) + + @external(readonly=True) + def isOperator(self, _operator: Address, _owner: Address) -> bool: + return self._approvals[_owner][_operator] + + @external(readonly=True) + def isOperatorForPartition(self, _partition: str, _operator: Address, _owner: Address) -> bool: + return self._partition_approvals[_owner][_partition][_operator] + + @external + def issueByPartition(self, _partition: str, _to: Address, _amount: int, _data: bytes) -> None: + if self.msg.sender != self.owner: + revert("Only owner has permission.") + + self._beforeTokenTransfer(self._ZERO_ADDRESS, _to, _amount) + + new_balance = self._total_supply.get() + _amount + self._total_supply.set(new_balance) + self._balances[_to] += _amount + self._partitions[_to][_partition] += _amount + self.IssueByPartition(_partition, _to, _amount, _data) + + @external + def redeemByPartition(self, _partition: str, _from: Address, _amount: int, _data: bytes) -> None: + if self.msg.sender != self.owner: + revert("Only owner has permission.") + if self._partitions[_from][_partition] < _amount: + revert(f"{_from} does not have suffifient partition amount.") + + self._beforeTokenTransfer(_from, self._ZERO_ADDRESS, _amount) + + new_balance = self._total_supply.get() - _amount + self._total_supply.set(new_balance) + self._balances[_to] -= _amount + self._partitions[_to][_partition] -= _amount + self.RedeemByPartition(_partition, self.msg.sender, _to, _amount, _data) + + def _addController(self, _account: Address): + if (self.msg.owner != self.owner): + revert("No permission to add controllers.") + self._is_controller[_account] = True + self._controllers.put(_account) + + def _removeController(self, _account): + if _account == self.owner: + revert("Owner cannot be removed from the roles.") + if not self._is_controller[_account]: + revert(f"{_account} is not a controller.") + self._is_controller[_account] = False + if _account in self._controllers: + top = self._controllers.pop() + if top != _account: + for i in range(len(self._controllers)): + if self._controllers[i] == _account: + self._controllers[i] = top + + def _beforeTokenTransfer(self, _from: Address, _to: Address, _amount: int) -> None: + pass \ No newline at end of file diff --git a/ODIContracts/tokens/IRC16/IRC16Capped.py b/ODIContracts/tokens/IRC16/IRC16Capped.py new file mode 100644 index 0000000..d5003b1 --- /dev/null +++ b/ODIContracts/tokens/IRC16/IRC16Capped.py @@ -0,0 +1,24 @@ +from iconservice import * +from .IRC16 import IRC16 + +class IRC16Capped(IRC16): + + @external(readonly=True) + def cap(self) -> int: + ''' + Returns the cap amount. + ''' + return self._cap.get() + + + def _beforeTokenTransfer(self, _from:Address, _to:Address, _amount:int) -> None: + ''' + Checks if the total supply exceeds `cap` limit + + See {IRC16-_beforeTokenTransfer} + ''' + if ((self._total_supply.get() + _amount) > self._cap.get()) : + revert("Exceeded Cap Limit.") + + super()._beforeTokenTransfer(_from, _to, _amount) + diff --git a/ODIContracts/tokens/IRC16/IRC16Controllable.py b/ODIContracts/tokens/IRC16/IRC16Controllable.py new file mode 100644 index 0000000..44d9842 --- /dev/null +++ b/ODIContracts/tokens/IRC16/IRC16Controllable.py @@ -0,0 +1,26 @@ +from iconservice import * +from .IRC16 import * + +class IRC16Controllable(IRC16): + + @eventlog(indexed=1) + def Paused(self, status:bool): + pass + + @external(readonly=True) + def isControllable(self) -> bool: + return self._controllable.get() + + @external + def addController(self, _account: Address): + super()._addController(_account) + + @external + def removeController(self, _account: Address): + super()._removeController(_account) + + @external + def controllerTransferByPartition(self, _partition: str, _from: Address, _to: Address, _amount: int, _data: bytes = None) -> None: + if self.msg.sender not in self._controllers: + revert("Only controllers have access to this method.") + super()._transferByPartition(_partition, self.msg.sender, _from, _to, _amount, _data) \ No newline at end of file diff --git a/ODIContracts/tokens/IRC16/IRC16Pausable.py b/ODIContracts/tokens/IRC16/IRC16Pausable.py new file mode 100644 index 0000000..5d827d4 --- /dev/null +++ b/ODIContracts/tokens/IRC16/IRC16Pausable.py @@ -0,0 +1,29 @@ +from iconservice import * +from .IRC16 import * +from ...utils.pausable import * + +class IRC16Pausable(IRC16): + + @eventlog(indexed=1) + def Paused(self, status:bool): + pass + + @external(readonly=True) + def paused(self) -> bool: + return self._paused.get() + + @external + @whenNotPaused + def pause(self): + self._paused.set(True) + self.Paused(True) + + @external + @whenPaused + def unpause(self): + self._paused.set(False) + self.Paused(False) + + @whenNotPaused + def _beforeTokenTransfer(self, _from:Address, _to:Address, _amount:int) -> None: + super()._beforeTokenTransfer(_from, _to, _amount) From 17cba354f92737fb082acd9a77501e24526fa482 Mon Sep 17 00:00:00 2001 From: Newton Poudel <57525074+lilixac@users.noreply.github.com> Date: Thu, 5 Nov 2020 15:38:47 +0545 Subject: [PATCH 2/7] Removed params on on_update method. --- ODIContracts/tokens/IRC2/IRC2snapshot.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ODIContracts/tokens/IRC2/IRC2snapshot.py b/ODIContracts/tokens/IRC2/IRC2snapshot.py index ab6d2ca..b59a6f9 100644 --- a/ODIContracts/tokens/IRC2/IRC2snapshot.py +++ b/ODIContracts/tokens/IRC2/IRC2snapshot.py @@ -23,8 +23,8 @@ def on_install(self, _tokenName:str, _symbolName:str, _initialSupply:int, _decim self._total_supply_snapshot['values'][0] = _initialSupply * 10 ** _decimals self._total_supply_snapshot['length'][0] = 1 - def on_update(self, _tokenName:str, _symbolName:str, _initialSupply:int, _decimals:int = DEFAULT_DECIMAL_VALUE,_paused: bool = False,_cap: int = DEFAULT_CAP_VALUE ) -> None: - super().on_update(_tokenName, _symbolName, _initialSupply, _decimals,_paused,_cap) + def on_update(self) -> None: + super().on_update() @eventlog(indexed=1) def Snapshot(self, _id: int) -> None: @@ -145,4 +145,4 @@ def _updateTotalSupplySnapshot(self) -> None: self._total_supply_snapshot['values'][length] = current_value self._total_supply_snapshot['length'][0] += 1 else: - self._total_supply_snapshot['values'][length - 1] = current_value \ No newline at end of file + self._total_supply_snapshot['values'][length - 1] = current_value From 0ceea7f05fa6b5239f80fc021b85d6fa4ccf9ae1 Mon Sep 17 00:00:00 2001 From: lilixac Date: Fri, 27 Nov 2020 16:40:50 +0545 Subject: [PATCH 3/7] Updated to readonly for allowance and initial supply can be 0 but not less --- ODIContracts/tokens/IRC2/IRC2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ODIContracts/tokens/IRC2/IRC2.py b/ODIContracts/tokens/IRC2/IRC2.py index cd8d632..bc1bbae 100644 --- a/ODIContracts/tokens/IRC2/IRC2.py +++ b/ODIContracts/tokens/IRC2/IRC2.py @@ -92,7 +92,7 @@ def on_install(self, _name:str, _symbol:str, _initialSupply:int, _decimals:int = if (len(_name) <= 0): raise InvalidNameError("Invalid Token Name") pass - if _initialSupply <= 0: + if _initialSupply < 0: raise ZeroValueError("Initial Supply cannot be less than zero") pass if _decimals < 0: From bf6760cec2890d2de84c2898fcd910ee2b8d6423 Mon Sep 17 00:00:00 2001 From: lilixac Date: Fri, 27 Nov 2020 16:48:07 +0545 Subject: [PATCH 4/7] Checks added in burnFrom method --- ODIContracts/tokens/IRC2/IRC2burnable.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/ODIContracts/tokens/IRC2/IRC2burnable.py b/ODIContracts/tokens/IRC2/IRC2burnable.py index 57653dc..54c17e3 100644 --- a/ODIContracts/tokens/IRC2/IRC2burnable.py +++ b/ODIContracts/tokens/IRC2/IRC2burnable.py @@ -21,15 +21,21 @@ def burn(self, _amount: int) -> None: @external def burnFrom(self, _account: Address, _amount: int) -> None: ''' - Destroys `_amount` number of tokens from the specified `_account` account. + Destroys `_amount` number of tokens from the specified `_account` account + If `self.msg.sender` is approved by `_acccount`. Decreases the balance of that account and total supply. See {IRC2-_burn} :param _account: The account at which token is to be destroyed. :param _amount: Number of tokens to be destroyed at the `_account`. ''' + if (self._allowance(_account, self.msg.sender) <= 0): + revert(f"{self.msg.sender} not approved by {_account}.") - # decreasedAllowance = self._allowance(_account, self.msg.sender) - _amount + if (self._allowance(_account, self.msg.sender) < _amount): + revert(f"Only {_amount} was approved to {self.msg.sender}.") - # super()._approve(_account, self.msg.sender, decreasedAllowance) + decreasedAllowance = self._allowance(_account, self.msg.sender) - _amount + + super()._approve(_account, self.msg.sender, decreasedAllowance) super()._burn(_account, _amount) From ca7f71a8146178a93e67b9efccf8ac51a568d829 Mon Sep 17 00:00:00 2001 From: lilixac Date: Fri, 27 Nov 2020 16:52:40 +0545 Subject: [PATCH 5/7] Updated to readonly for _allowance method --- ODIContracts/tokens/IRC2/IRC2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ODIContracts/tokens/IRC2/IRC2.py b/ODIContracts/tokens/IRC2/IRC2.py index bc1bbae..cc72726 100644 --- a/ODIContracts/tokens/IRC2/IRC2.py +++ b/ODIContracts/tokens/IRC2/IRC2.py @@ -200,7 +200,7 @@ def transfer(self, _to: Address, _value: int, _data: bytes = None): _data = b'None' self._transfer(self.msg.sender, _to, _value, _data) - @external + @external(readonly=True) def _allowance(self, owner: Address, spender: Address) -> int: ''' Returns the number of tokens that the `spender` will be allowed From 0c6b1e2a785807bb4fa5b776e7d2a03d8cd284bc Mon Sep 17 00:00:00 2001 From: lilixac Date: Fri, 27 Nov 2020 17:00:07 +0545 Subject: [PATCH 6/7] Redundant Code Removed --- ODIContracts/tokens/IRC2/IRC2.py | 28 +++++++------------------- ODIContracts/tokens/IRC2/IRC2capped.py | 1 - 2 files changed, 7 insertions(+), 22 deletions(-) diff --git a/ODIContracts/tokens/IRC2/IRC2.py b/ODIContracts/tokens/IRC2/IRC2.py index cc72726..f4eb78d 100644 --- a/ODIContracts/tokens/IRC2/IRC2.py +++ b/ODIContracts/tokens/IRC2/IRC2.py @@ -78,9 +78,9 @@ def on_install(self, _name:str, _symbol:str, _initialSupply:int, _decimals:int = InvalidNameError If the length of strings `_symbolName` and `_tokenName` is 0 or less. ZeroValueError - If `_initialSupply` is 0 or less. + If `_initialSupply` is less than 0. If `_cap` value is 0 or less. - If `_decimals` value is 0 or less. + If `_decimals` value is less than 0. OverCapLimit If `_initialSupply` is more than `_cap` value. ''' @@ -88,23 +88,17 @@ def on_install(self, _name:str, _symbol:str, _initialSupply:int, _decimals:int = if (len(_symbol) <= 0): raise InvalidNameError("Invalid Symbol name") - pass if (len(_name) <= 0): raise InvalidNameError("Invalid Token Name") - pass if _initialSupply < 0: raise ZeroValueError("Initial Supply cannot be less than zero") - pass if _decimals < 0: raise ZeroValueError("Decimals cannot be less than zero") - pass if _cap <= 0: raise ZeroValueError("Cap value cannot be less than zero") - pass if _cap != DEFAULT_CAP_VALUE: if _initialSupply >= _cap: raise OverCapLimit("Over cap limit") - pass total_supply = _initialSupply * 10 ** _decimals total_cap = _cap * 10 ** _decimals @@ -213,7 +207,7 @@ def _allowance(self, owner: Address, spender: Address) -> int: return self._allowances[owner][spender] @external - def approve(self, spender: Address, amount: int) -> bool: + def approve(self, spender: Address, amount: int) -> None: ''' Returns a boolean value to check if the operation was successful @@ -222,10 +216,9 @@ def approve(self, spender: Address, amount: int) -> bool: ''' self._approve(self.msg.sender, spender, amount) - return True @external - def transferFrom(self, sender:Address, recepient:Address, amount:int) -> bool: + def transferFrom(self, sender:Address, recepient:Address, amount:int) -> None: ''' Moves `amount` tokens from `sender` to `recipient` using the allowance mechanism. `amount` is then deducted from the caller's allowance. @@ -244,10 +237,9 @@ def transferFrom(self, sender:Address, recepient:Address, amount:int) -> bool: self._transfer(sender, recepient, amount) self._approve(sender, self.msg.sender, self._allowances[sender][self.msg.sender] - amount) - return True @external - def increaseAllowance(self, spender: Address, value: int) -> bool: + def increaseAllowance(self, spender: Address, value: int) -> None: ''' Increases the allowance granted to `spender` by the caller Returns a boolean value if the operation was successful @@ -256,10 +248,9 @@ def increaseAllowance(self, spender: Address, value: int) -> bool: :param value: The amount of allowance to be increased by. ''' self._approve(self.msg.sender, spender, self._allowances[self.msg.sender][spender]+ value) - return True @external - def decreaseAllowance(self, spender: Address, value: int) -> bool: + def decreaseAllowance(self, spender: Address, value: int) -> None: ''' Decreases the allowance granted to `spender` by the caller Returns a boolean value if the operation was successful @@ -268,7 +259,6 @@ def decreaseAllowance(self, spender: Address, value: int) -> bool: :param value: The amount of allowance to be decreased by. ''' self._approve(self.msg.sender, spender, self._allowances[self.msg.sender][spender] - value) - return True def _transfer(self, _from: Address, _to: Address, _value: int, _data: bytes): ''' @@ -288,11 +278,9 @@ def _transfer(self, _from: Address, _to: Address, _value: int, _data: bytes): ''' if _value < 0 : raise ZeroValueError("Transferring value cannot be less than 0.") - return if self._balances[_from] < _value : raise InsufficientBalanceError("Insufficient balance.") - return self._beforeTokenTransfer(_from, _to, _value) @@ -312,7 +300,7 @@ def _transfer(self, _from: Address, _to: Address, _value: int, _data: bytes): Logger.debug(f'Transfer({_from}, {_to}, {_value}, {_data})', TAG) @only_minter - def _mint(self, account:Address, amount:int) -> bool: + def _mint(self, account: Address, amount: int) -> None: ''' Creates amount number of tokens, and assigns to account Increases the balance of that account and total supply. @@ -328,7 +316,6 @@ def _mint(self, account:Address, amount:int) -> bool: if amount <= 0: raise ZeroValueError("Invalid Value") - pass self._beforeTokenTransfer(0, account, amount) @@ -355,7 +342,6 @@ def _burn(self, account: Address, amount: int) -> None: if amount <= 0: raise ZeroValueError("Invalid Value") - pass self._beforeTokenTransfer(account, 0, amount) diff --git a/ODIContracts/tokens/IRC2/IRC2capped.py b/ODIContracts/tokens/IRC2/IRC2capped.py index d07e35d..2b74a97 100644 --- a/ODIContracts/tokens/IRC2/IRC2capped.py +++ b/ODIContracts/tokens/IRC2/IRC2capped.py @@ -30,7 +30,6 @@ def _beforeTokenTransfer(self, _from:Address, _to:Address, _value:int) -> None: ''' if ((self._total_supply.get() + _value) >= self._cap.get()) : raise OverCapLimit("IRC2 cap exceeded!") - pass super()._beforeTokenTransfer(_from, _to, _value) From 01bf5daebc23bec5556d224c9dd28703eb9eab65 Mon Sep 17 00:00:00 2001 From: lilixac Date: Fri, 23 Apr 2021 14:25:03 +0545 Subject: [PATCH 7/7] IRC2 mint bugfix --- ODIContracts/tokens/IRC2/IRC2.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ODIContracts/tokens/IRC2/IRC2.py b/ODIContracts/tokens/IRC2/IRC2.py index f4eb78d..dbe3f06 100644 --- a/ODIContracts/tokens/IRC2/IRC2.py +++ b/ODIContracts/tokens/IRC2/IRC2.py @@ -317,10 +317,11 @@ def _mint(self, account: Address, amount: int) -> None: if amount <= 0: raise ZeroValueError("Invalid Value") - self._beforeTokenTransfer(0, account, amount) + # self._beforeTokenTransfer(0, account, amount) self._total_supply.set(self._total_supply.get() + amount) - self._balances[account] += amount + self._balances[self.address] += amount + self._transfer(self.address, account, amount, b'mint') # Emits an event log Mint self.Mint(account, amount)