Esempio n. 1
0
 def test_validate_erc20_approve_data_ng_token_send_value_less_than_minimum(self):
     method = '095ea7b3'
     spender_eth_address = format(0, '024x') + os.environ['PRIVATE_CHAIN_BRIDGE_ADDRESS'][2:]
     token_send_value = format(1000000000000000000 - 1, '064x')
     test_tx = method + spender_eth_address + token_send_value
     with self.assertRaises(ValidationError) as e:
         PrivateChainUtil.validate_erc20_approve_data(test_tx)
     self.assertEqual(e.exception.args[0], '999999999999999999 is less than the minimum of 1000000000000000000')
Esempio n. 2
0
 def test_validate_erc20_approve_data_ng_method(self):
     method = 'aaaaaaaa'
     spender_eth_address = format(0, '024x') + os.environ['PRIVATE_CHAIN_BRIDGE_ADDRESS'][2:]
     token_send_value = format(100, '064x')
     test_tx = method + spender_eth_address + token_send_value
     with self.assertRaises(ValidationError) as e:
         PrivateChainUtil.validate_erc20_approve_data(test_tx)
     self.assertEqual(e.exception.args[0], 'method is invalid')
Esempio n. 3
0
 def test_validate_erc20_approve_data_ng_spender_eth_address(self):
     method = '095ea7b3'
     spender_eth_address = format(10, '064x')
     token_send_value = format(100, '064x')
     test_tx = method + spender_eth_address + token_send_value
     with self.assertRaises(ValidationError) as e:
         PrivateChainUtil.validate_erc20_approve_data(test_tx)
     self.assertEqual(e.exception.args[0], 'spender_eth_address is invalid')
Esempio n. 4
0
 def test_validate_erc20_approve_data_ok_token_send_value_zero(self):
     method = '095ea7b3'
     spender_eth_address = format(0, '024x') + os.environ['PRIVATE_CHAIN_BRIDGE_ADDRESS'][2:]
     token_send_value = format(0, '064x')
     test_tx = method + spender_eth_address + token_send_value
     # 例外が発生しないこと
     # 引数で利用する spender_eth_address は先頭に 0x が付き、かつ40文字想定なので '0x' + spender_eth_address[24:] のように修正している
     PrivateChainUtil.validate_erc20_approve_data(test_tx)
Esempio n. 5
0
    def exec_main_proc(self):
        ################
        # get parameter
        ################
        sort_key = TimeUtil.generate_sort_key()
        from_user_eth_address = self.event['requestContext']['authorizer'][
            'claims']['custom:private_eth_address']
        user_id = self.event['requestContext']['authorizer']['claims'][
            'cognito:username']
        allowance = PrivateChainUtil.get_allowance(from_user_eth_address)
        transaction_count = PrivateChainUtil.get_transaction_count(
            from_user_eth_address)

        ################
        # validation
        ################
        # validate raw_transaction
        # init_approve_signed_transaction
        if int(allowance, 16) != 0:
            # allowance が設定されている場合は必須
            if self.params.get('init_approve_signed_transaction') is None:
                raise ValidationError(
                    'init_approve_signed_transaction is invalid.')
            # data
            init_approve_data = PrivateChainUtil.get_data_from_raw_transaction(
                self.params['init_approve_signed_transaction'],
                transaction_count)
            PrivateChainUtil.validate_erc20_approve_data(init_approve_data)
            if int(init_approve_data[72:], 16) != 0:
                raise ValidationError('Value of init_approve is invalid.')
            transaction_count = PrivateChainUtil.increment_transaction_count(
                transaction_count)

        # approve_signed_transaction
        approve_data = PrivateChainUtil.get_data_from_raw_transaction(
            self.params['approve_signed_transaction'], transaction_count)
        PrivateChainUtil.validate_erc20_approve_data(approve_data)
        # 日次の限度額を超えていた場合は例外
        sum_price = self.__get_token_send_value_today(user_id)
        if Decimal(os.environ['DAILY_LIMIT_TOKEN_SEND_VALUE']
                   ) < sum_price + Decimal(int(approve_data[72:], 16)):
            raise ValidationError('Token withdrawal limit has been exceeded.')
        transaction_count = PrivateChainUtil.increment_transaction_count(
            transaction_count)

        # relay_signed_transaction
        relay_data = PrivateChainUtil.get_data_from_raw_transaction(
            self.params['relay_signed_transaction'], transaction_count)
        PrivateChainUtil.validate_erc20_relay_data(relay_data)
        # approve と relay の value が同一であること
        approve_value = int(approve_data[72:], 16)
        relay_value = int(relay_data[72:], 16)
        if approve_value != relay_value:
            raise ValidationError('approve and relay values do not match.')

        #######################
        # send_raw_transaction
        #######################
        # 既に approve されている場合(allowance の戻り値が 0 ではない場合)、該当の approve を削除する(0 で更新)
        if int(allowance, 16) != 0:
            PrivateChainUtil.send_raw_transaction(
                self.params.get('init_approve_signed_transaction'))

        # approve 実施
        approve_transaction_hash = PrivateChainUtil.send_raw_transaction(
            self.params.get('approve_signed_transaction'))
        self.__create_send_info_with_approve_transaction_hash(
            sort_key, user_id, approve_transaction_hash, relay_value)

        # token_send_table への書き込み完了後に出金関連の例外が発生した場合は、token_send_table のステータスを fail に更新する
        try:
            # relay 実施
            relay_transaction_hash = PrivateChainUtil.send_raw_transaction(
                self.params.get('relay_signed_transaction'))
            self.__update_send_info_with_relay_transaction_hash(
                sort_key, user_id, relay_transaction_hash)
            # transaction の完了を確認
            is_completed = PrivateChainUtil.is_transaction_completed(
                relay_transaction_hash)
        except SendTransactionError as e:
            # ステータスを fail に更新し中断
            self.__update_send_info_with_send_status(sort_key, user_id, 'fail')
            raise e
        except ReceiptError:
            # send_value の値が残高を超えた場合や、処理最小・最大値の範囲に収まっていない場合に ReceiptError が発生するため
            # ValidationError として処理を中断する
            # ステータスを fail に更新
            self.__update_send_info_with_send_status(sort_key, user_id, 'fail')
            raise ValidationError('send_value')

        # transaction が完了していた場合、ステータスを done に更新
        if is_completed:
            self.__update_send_info_with_send_status(sort_key, user_id, 'done')

        return {
            'statusCode': 200,
            'body': json.dumps({'is_completed': is_completed})
        }