class EthereumTxWithTransfersResponseSerializer(serializers.Serializer):
    class Meta:
        model = EthereumTx
        exclude = ('block', )

    _from = EthereumAddressField(allow_null=False,
                                 allow_zero_address=True,
                                 source='_from')
    to = EthereumAddressField(allow_null=True, allow_zero_address=True)
    data = HexadecimalField()
    tx_hash = HexadecimalField()
    block_number = serializers.SerializerMethodField()
    block_timestamp = serializers.SerializerMethodField()
    transfers = TransferResponseSerializer(many=True)
    tx_type = serializers.SerializerMethodField()

    def get_tx_type(self, obj):
        return TxType.ETHEREUM_TRANSACTION.name

    def get_fields(self):
        result = super().get_fields()
        # Rename `_from` to `from`
        _from = result.pop('_from')
        result['from'] = _from
        return result

    def get_block_number(self, obj: EthereumTx):
        if obj.block:
            return obj.block.number

    def get_block_timestamp(self, obj: EthereumTx):
        if obj.block:
            return obj.block.timestamp
示例#2
0
class SafeResponseSerializer(serializers.Serializer):
    address = EthereumAddressField()
    master_copy = EthereumAddressField()
    nonce = serializers.IntegerField(min_value=0)
    threshold = serializers.IntegerField(min_value=1)
    owners = serializers.ListField(child=EthereumAddressField(), min_length=1)
    version = serializers.CharField()
class EthereumTxWithTransfersResponseSerializer(serializers.Serializer):
    class Meta:
        model = EthereumTx
        exclude = ("block", )

    execution_date = serializers.DateTimeField()
    _from = EthereumAddressField(allow_null=False,
                                 allow_zero_address=True,
                                 source="_from")
    to = EthereumAddressField(allow_null=True, allow_zero_address=True)
    data = HexadecimalField()
    tx_hash = HexadecimalField()
    block_number = serializers.SerializerMethodField()
    transfers = TransferWithTokenInfoResponseSerializer(many=True)
    tx_type = serializers.SerializerMethodField()

    def get_tx_type(self, obj) -> str:
        return TxType.ETHEREUM_TRANSACTION.name

    def get_fields(self):
        result = super().get_fields()
        # Rename `_from` to `from`
        _from = result.pop("_from")
        result["from"] = _from
        return result

    def get_block_number(self, obj: EthereumTx) -> Optional[int]:
        if obj.block_id:
            return obj.block_id
class TransferResponseSerializer(serializers.Serializer):
    type = serializers.SerializerMethodField()
    execution_date = serializers.DateTimeField()
    block_number = serializers.IntegerField(source="block")
    transaction_hash = Sha3HashField()
    to = EthereumAddressField()
    from_ = EthereumAddressField(source="_from", allow_zero_address=True)
    value = serializers.CharField(allow_null=True, source="_value")
    token_id = serializers.CharField(allow_null=True, source="_token_id")
    token_address = EthereumAddressField(allow_null=True, default=None)

    def get_fields(self):
        result = super().get_fields()
        # Rename `from_` to `from`
        from_ = result.pop("from_")
        result["from"] = from_
        return result

    def get_type(self, obj: TransferDict) -> str:
        if obj["token_address"] is None:
            return TransferType.ETHER_TRANSFER.name
        else:
            if obj["_value"] is not None:
                return TransferType.ERC20_TRANSFER.name
            elif obj["_token_id"] is not None:
                return TransferType.ERC721_TRANSFER.name
            else:
                return TransferType.UNKNOWN.name

    def validate(self, data):
        super().validate(data)
        if data["value"] is None and data["token_id"] is None:
            raise ValidationError("Both value and token_id cannot be null")
        return data
class DelegateDeleteSerializer(DelegateSignatureCheckerMixin,
                               serializers.Serializer):
    delegate = EthereumAddressField()
    delegator = EthereumAddressField()
    signature = HexadecimalField(min_length=65)

    def validate(self, data):
        super().validate(data)

        signature = data["signature"]
        delegate = data["delegate"]  # Delegate address to be added/removed
        delegator = data["delegator"]  # Delegator

        ethereum_client = EthereumClientProvider()
        # Tries to find a valid delegator using multiple strategies
        for operation_hash in DelegateSignatureHelper.calculate_all_possible_hashes(
                delegate):
            for signer in (delegate, delegator):
                if self.check_delegate_signature(ethereum_client, signature,
                                                 operation_hash, signer):
                    return data

        raise ValidationError(
            f"Signature does not match provided delegate={delegate} or delegator={delegator}"
        )
class TransferResponseSerializer(serializers.Serializer):
    type = serializers.SerializerMethodField()
    execution_date = serializers.DateTimeField()
    block_number = serializers.IntegerField()
    transaction_hash = Sha3HashField()
    to = EthereumAddressField()
    from_ = EthereumAddressField(source='_from')
    value = serializers.CharField()
    token_id = serializers.CharField()
    token_address = EthereumAddressField(allow_null=True, default=None)

    def get_fields(self):
        result = super().get_fields()
        # Rename `from_` to `from`
        from_ = result.pop('from_')
        result['from'] = from_
        return result

    def get_type(self, obj: Dict[str, Any]) -> str:
        if not obj.get('token_address'):
            return TransferType.ETHER_TRANSFER.name
        else:
            if obj.get('value') is not None:
                return TransferType.ERC20_TRANSFER.name
            elif obj.get('token_id') is not None:
                return TransferType.ERC721_TRANSFER.name

        return TransferType.UNKNOWN
示例#7
0
class InternalTxSerializer(serializers.ModelSerializer):
    class Meta:
        model = InternalTx
        exclude = ('id', )

    _from = EthereumAddressField(allow_null=False,
                                 allow_zero_address=True,
                                 source='_from')
    to = EthereumAddressField(allow_null=True, allow_zero_address=True)
    contract_address = EthereumAddressField(allow_null=True,
                                            allow_zero_address=True)
    data = HexadecimalField()
    code = HexadecimalField()
    output = HexadecimalField()
    tx_type = serializers.SerializerMethodField()
    call_type = serializers.SerializerMethodField()
    ethereum_tx = None

    def get_fields(self):
        result = super().get_fields()
        # Rename `_from` to `from`
        _from = result.pop('_from')
        result['from'] = _from
        return result

    def get_tx_type(self, obj) -> str:
        return EthereumTxType(obj.tx_type).name

    def get_call_type(self, obj) -> str:
        if obj.call_type is None:
            return None
        else:
            return EthereumTxCallType(obj.call_type).name
示例#8
0
class SafeMultisigEstimateTxSerializer(serializers.Serializer):
    safe = EthereumAddressField()
    to = EthereumAddressField()
    value = serializers.IntegerField(min_value=0)
    data = HexadecimalField(default=None, allow_null=True, allow_blank=True)
    operation = serializers.IntegerField(min_value=0)
    gas_token = EthereumAddressField(
        default=None, allow_null=True, allow_zero_address=True
    )

    def validate_operation(self, value):
        try:
            return SafeOperation(value).value
        except ValueError:
            raise ValidationError("Unknown operation")

    def validate(self, data):
        super().validate(data)

        if not data["to"] and not data["data"]:
            raise ValidationError("`data` and `to` cannot both be null")

        if not data["to"] and not data["data"]:
            raise ValidationError("`data` and `to` cannot both be null")

        if data["operation"] == SafeOperation.CREATE.value:
            raise ValidationError(
                "Operation CREATE not supported. Please use Gnosis Safe CreateLib"
            )
            #  if data['to']:
            #      raise ValidationError('Operation is Create, but `to` was provided')
            #  elif not data['data']:
            #      raise ValidationError('Operation is Create, but not `data` was provided')

        return data
class SafeMultisigTxResponseSerializer(serializers.Serializer):
    to = EthereumAddressField(allow_null=True, allow_zero_address=True)
    ethereum_tx = EthereumTxSerializer()
    value = serializers.IntegerField(min_value=0)
    data = HexadecimalField()
    timestamp = serializers.DateTimeField(source='created')
    operation = serializers.SerializerMethodField()
    safe_tx_gas = serializers.IntegerField(min_value=0)
    data_gas = serializers.IntegerField(min_value=0)
    gas_price = serializers.IntegerField(min_value=0)
    gas_token = EthereumAddressField(allow_null=True, allow_zero_address=True)
    refund_receiver = EthereumAddressField(allow_null=True,
                                           allow_zero_address=True)
    nonce = serializers.IntegerField(min_value=0)
    safe_tx_hash = Sha3HashField()
    tx_hash = serializers.SerializerMethodField()
    transaction_hash = serializers.SerializerMethodField(
        method_name='get_tx_hash')  # Retro compatibility

    def get_operation(self, obj):
        """
        Filters confirmations queryset
        :param obj: MultisigConfirmation instance
        :return: serialized queryset
        """
        return SafeOperation(obj.operation).name

    def get_tx_hash(self, obj):
        tx_hash = obj.ethereum_tx.tx_hash
        if tx_hash and isinstance(tx_hash, bytes):
            return tx_hash.hex()
        return tx_hash
class EthereumTxSerializer(serializers.ModelSerializer):
    class Meta:
        model = EthereumTx
        exclude = ('block', )

    _from = EthereumAddressField(allow_null=False,
                                 allow_zero_address=True,
                                 source='_from')
    to = EthereumAddressField(allow_null=True, allow_zero_address=True)
    data = HexadecimalField()
    tx_hash = HexadecimalField()
    block_number = serializers.SerializerMethodField()
    block_timestamp = serializers.SerializerMethodField()

    def get_fields(self):
        result = super().get_fields()
        # Rename `_from` to `from`
        _from = result.pop('_from')
        result['from'] = _from
        return result

    def get_block_number(self, obj: EthereumTx):
        if obj.block:
            return obj.block.number

    def get_block_timestamp(self, obj: EthereumTx):
        if obj.block:
            return obj.block.timestamp
class SafeCreationInfoResponseSerializer(serializers.Serializer):
    created = serializers.DateTimeField()
    creator = EthereumAddressField()
    factory_address = EthereumAddressField()
    master_copy = EthereumAddressField(allow_null=True)
    setup_data = HexadecimalField(allow_null=True)
    transaction_hash = Sha3HashField()
class SafeDelegateDeleteSerializer(serializers.Serializer):
    safe = EthereumAddressField()
    delegate = EthereumAddressField()
    signature = HexadecimalField(min_length=130)

    def check_signature(self, signature: bytes, operation_hash: bytes, safe_owners: List[str]) -> Optional[str]:
        """
        Checks signature and returns a valid owner if found, None otherwise
        :param signature:
        :param operation_hash:
        :param safe_owners:
        :return: Valid delegator address if found, None otherwise
        """
        safe_signatures = SafeSignature.parse_signature(signature, operation_hash)
        if not safe_signatures:
            raise ValidationError('Signature is not valid')
        elif len(safe_signatures) > 1:
            raise ValidationError('More than one signatures detected, just one is expected')

        safe_signature = safe_signatures[0]
        delegator = safe_signature.owner
        if delegator in safe_owners:
            if not safe_signature.is_valid():
                raise ValidationError(f'Signature of type={safe_signature.signature_type.name} '
                                      f'for delegator={delegator} is not valid')
            return delegator

    def validate(self, data):
        super().validate(data)

        if not SafeContract.objects.filter(address=data['safe']).exists():
            raise ValidationError(f"Safe={data['safe']} does not exist or it's still not indexed")

        ethereum_client = EthereumClientProvider()
        safe = Safe(data['safe'], ethereum_client)

        # Check owners and pending owners
        try:
            safe_owners = safe.retrieve_owners(block_identifier='pending')
        except BadFunctionCallOutput:  # Error using pending block identifier
            safe_owners = safe.retrieve_owners(block_identifier='latest')

        signature = data['signature']
        delegate = data['delegate']  # Delegate address to be added

        # Tries to find a valid delegator using multiple strategies
        for operation_hash in (DelegateSignatureHelper.calculate_hash(delegate),
                               DelegateSignatureHelper.calculate_hash(delegate, eth_sign=True),
                               DelegateSignatureHelper.calculate_hash(delegate, previous_topt=True),
                               DelegateSignatureHelper.calculate_hash(delegate, eth_sign=True, previous_topt=True)):
            delegator = self.check_signature(signature, operation_hash, safe_owners)
            if delegator:
                break

        if not delegator:
            raise ValidationError('Signing owner is not an owner of the Safe')

        data['delegator'] = delegator
        return data
class SafeCreationResponseSerializer(serializers.Serializer):
    signature = SignatureResponseSerializer()
    tx = TransactionResponseSerializer()
    tx_hash = Sha3HashField()
    payment = serializers.CharField()
    payment_token = EthereumAddressField(allow_null=True, allow_zero_address=True)
    safe = EthereumAddressField()
    deployer = EthereumAddressField()
    funder = EthereumAddressField()
class SafeCreation2Serializer(ThresholdValidatorSerializerMixin,
                              serializers.Serializer):
    salt_nonce = serializers.IntegerField(min_value=0,
                                          max_value=2**256 - 1)  # Uint256
    owners = serializers.ListField(child=EthereumAddressField(), min_length=1)
    threshold = serializers.IntegerField(min_value=1)
    payment_token = EthereumAddressField(default=None,
                                         allow_null=True,
                                         allow_zero_address=True)
class SafeCreationSerializer(ThresholdValidatorSerializerMixin,
                             serializers.Serializer):
    s = serializers.IntegerField(min_value=SIGNATURE_S_MIN_VALUE,
                                 max_value=SIGNATURE_S_MAX_VALUE)
    owners = serializers.ListField(child=EthereumAddressField(), min_length=1)
    threshold = serializers.IntegerField(min_value=1)
    payment_token = EthereumAddressField(default=None,
                                         allow_null=True,
                                         allow_zero_address=True)
class SafeInfoResponseSerializer(serializers.Serializer):
    address = EthereumAddressField()
    nonce = serializers.IntegerField()
    threshold = serializers.IntegerField()
    owners = serializers.ListField(child=EthereumAddressField())
    master_copy = EthereumAddressField()
    modules = serializers.ListField(child=EthereumAddressField())
    fallback_handler = EthereumAddressField()
    version = serializers.CharField()
class SafeCreation2ResponseSerializer(serializers.Serializer):
    safe = EthereumAddressField()
    master_copy = EthereumAddressField()
    proxy_factory = EthereumAddressField()
    payment_token = EthereumAddressField(allow_zero_address=True)
    payment = serializers.CharField()
    payment_receiver = EthereumAddressField(allow_zero_address=True)
    setup_data = HexadecimalField()
    gas_estimated = serializers.CharField()
    gas_price_estimated = serializers.CharField()
class SafeDelegateDeleteSerializer(serializers.Serializer):
    safe = EthereumAddressField()
    delegate = EthereumAddressField()
    signature = HexadecimalField(min_length=130)

    def validate(self, data):
        super().validate(data)

        if not SafeContract.objects.filter(address=data['safe']).exists():
            raise ValidationError(
                f"Safe={data['safe']} does not exist or it's still not indexed"
            )

        ethereum_client = EthereumClientProvider()
        safe = Safe(data['safe'], ethereum_client)

        # Check owners and pending owners
        try:
            safe_owners = safe.retrieve_owners(block_identifier='pending')
        except BadFunctionCallOutput:  # Error using pending block identifier
            safe_owners = safe.retrieve_owners(block_identifier='latest')

        signature = data['signature']
        delegate = data['delegate']
        operation_hash = DelegateSignatureHelper.calculate_hash(delegate)
        safe_signatures = SafeSignature.parse_signature(
            signature, operation_hash)
        if not safe_signatures:
            raise ValidationError('Cannot a valid signature')
        elif len(safe_signatures) > 1:
            raise ValidationError(
                'More than one signatures detected, just one is expected')

        safe_signature = safe_signatures[0]
        delegator = safe_signature.owner
        if delegator not in safe_owners:
            if safe_signature.signature_type == SafeSignatureType.EOA:
                # Maybe it's an `eth_sign` signature without Gnosis Safe `v + 4`, let's try
                safe_signatures = SafeSignature.parse_signature(
                    signature,
                    DelegateSignatureHelper.calculate_hash(delegate,
                                                           eth_sign=True))
                safe_signature = safe_signatures[0]
                delegator = safe_signature.owner
            if delegator not in safe_owners:
                raise ValidationError(
                    'Signing owner is not an owner of the Safe')

        if not safe_signature.is_valid():
            raise ValidationError(
                f'Signature of type={safe_signature.signature_type.name} for delegator={delegator} '
                f'is not valid')

        data['delegator'] = delegator
        return data
class SafeCreationInfoResponseSerializer(serializers.Serializer):
    created = serializers.DateTimeField()
    creator = EthereumAddressField()
    transaction_hash = Sha3HashField()
    factory_address = EthereumAddressField()
    master_copy = EthereumAddressField(allow_null=True)
    setup_data = HexadecimalField(allow_null=True)
    data_decoded = serializers.SerializerMethodField()

    def get_data_decoded(self, obj: SafeCreationInfo) -> Dict[str, Any]:
        return get_data_decoded_from_data(obj.setup_data or b'')
class SafeMultisigEstimateTxResponseV2Serializer(serializers.Serializer):
    """
    Same as `SafeMultisigEstimateTxResponseSerializer`, but formatting `big integers` as `strings`
    """
    safe_tx_gas = serializers.CharField()
    base_gas = serializers.CharField()
    data_gas = serializers.CharField()
    operational_gas = serializers.CharField()
    gas_price = serializers.CharField()
    last_used_nonce = serializers.IntegerField(min_value=0, allow_null=True)
    gas_token = EthereumAddressField(allow_null=True, allow_zero_address=True)
    refund_receiver = EthereumAddressField(allow_zero_address=True)
class IncomingTransactionResponseSerializer(serializers.Serializer):
    execution_date = serializers.DateTimeField()
    block_number = serializers.IntegerField()
    transaction_hash = Sha3HashField()
    to = EthereumAddressField()
    from_ = EthereumAddressField(source='_from')
    value = serializers.CharField()
    token_address = EthereumAddressField(allow_null=True, default=None)

    def get_fields(self):
        result = super().get_fields()
        # Rename `from_` to `from`
        from_ = result.pop('from_')
        result['from'] = from_
        return result
示例#22
0
class NotificationSerializer(SignedMessageSerializer):
    devices = serializers.ListField(child=EthereumAddressField(), min_length=1)
    message = serializers.CharField(
        max_length=4096)  # 4Kb, expecting UTF-8 characters to get into 1 Byte

    def validate_message(self, data):
        try:
            json.loads(data)
        except json.JSONDecodeError:
            raise ValidationError("Message must be a valid stringified JSON")
        return data

    def validate(self, data):
        super().validate(data)
        devices = data['devices']
        if len(set(devices)) != len(devices):
            raise ValidationError("Duplicated addresses are forbidden")

        signing_address = data['signing_address']
        if signing_address in devices:
            raise ValidationError(
                "Signing address cannot be in the destination addresses")

        return data

    def get_hashed_fields(self, data: Dict[str, Any]) -> Tuple[str]:
        return data['message']
class SafeContractSerializer(serializers.Serializer):
    created = serializers.DateTimeField()
    address = EthereumAddressField()
    tokens_with_balance = serializers.SerializerMethodField()

    def get_tokens_with_balance(self, obj):
        return StatsServiceProvider().get_balances(obj.address)
class SafeMultisigTransactionEstimateSerializer(serializers.Serializer):
    to = EthereumAddressField()
    value = serializers.IntegerField(min_value=0)
    data = HexadecimalField(default=None, allow_null=True, allow_blank=True)
    operation = serializers.IntegerField(min_value=0)

    def save(self, **kwargs):
        safe_address = self.context["safe_address"]
        ethereum_client = EthereumClientProvider()
        safe = Safe(safe_address, ethereum_client)
        exc = None
        # Retry thrice to get an estimation
        for _ in range(3):
            try:
                safe_tx_gas = safe.estimate_tx_gas(
                    self.validated_data["to"],
                    self.validated_data["value"],
                    self.validated_data["data"],
                    self.validated_data["operation"],
                )
                return {"safe_tx_gas": safe_tx_gas}
            except (IOError, ValueError) as _exc:
                exc = _exc
        raise NodeConnectionException(
            f"Node connection error when estimating gas for Safe {safe_address}"
        ) from exc
class ContractSerializer(serializers.Serializer):
    address = EthereumAddressField()
    name = serializers.CharField()
    display_name = serializers.CharField()
    logo_uri = serializers.ImageField(source="logo")
    contract_abi = ContractAbiSerializer()
    trusted_for_delegate_call = serializers.BooleanField()
class ContractSerializer(serializers.Serializer):
    address = EthereumAddressField()
    name = serializers.SerializerMethodField()
    logo_uri = serializers.ImageField(source='logo')
    contract_abi = ContractAbiSerializer()

    def get_name(self, obj: Contract):
        return obj.get_main_name()
class SafeMultisigEstimateTxResponseSerializer(serializers.Serializer):
    safe_tx_gas = serializers.IntegerField(min_value=0)
    base_gas = serializers.IntegerField(min_value=0)
    data_gas = serializers.IntegerField(min_value=0)
    operational_gas = serializers.IntegerField(min_value=0)
    gas_price = serializers.IntegerField(min_value=0)
    last_used_nonce = serializers.IntegerField(min_value=0, allow_null=True)
    gas_token = EthereumAddressField(allow_null=True, allow_zero_address=True)
class MasterCopyResponseSerializer(serializers.Serializer):
    address = EthereumAddressField()
    version = serializers.CharField()
    deployer = serializers.CharField()
    deployed_block_number = serializers.IntegerField(
        source='initial_block_number')
    last_indexed_block_number = serializers.IntegerField(
        source='tx_block_number')
示例#29
0
class SafeMultisigTxSerializerV1(SafeMultisigEstimateTxSerializer):
    """
    Version 1.0.0 of the Safe changes `data_gas` to `base_gas`
    """
    safe_tx_gas = serializers.IntegerField(min_value=0)
    base_gas = serializers.IntegerField(min_value=0)
    gas_price = serializers.IntegerField(min_value=0)
    refund_receiver = EthereumAddressField(default=None,
                                           allow_null=True,
                                           allow_zero_address=True)
    nonce = serializers.IntegerField(min_value=0)
示例#30
0
class SafeMultisigTxSerializer(SafeMultisigEstimateTxSerializer):
    """
    DEPRECATED, use `SafeMultisigTxSerializerV1` instead
    """
    safe_tx_gas = serializers.IntegerField(min_value=0)
    data_gas = serializers.IntegerField(min_value=0)
    gas_price = serializers.IntegerField(min_value=0)
    refund_receiver = EthereumAddressField(default=None,
                                           allow_null=True,
                                           allow_zero_address=True)
    nonce = serializers.IntegerField(min_value=0)