From b6af076ed5cc126ea4175a71aaa7b65845084242 Mon Sep 17 00:00:00 2001 From: Bastien CHAMAGNE Date: Thu, 4 May 2023 09:24:03 +0200 Subject: [PATCH 1/2] SC raise on invalid amount --- .../legacy/transaction_statements.ex | 9 ++++ .../interpreter/library/contract_test.exs | 54 +++++++++++++++++++ test/archethic/contracts/interpreter_test.exs | 28 ++++++++++ 3 files changed, 91 insertions(+) diff --git a/lib/archethic/contracts/interpreter/legacy/transaction_statements.ex b/lib/archethic/contracts/interpreter/legacy/transaction_statements.ex index 7f9cf7128..a5f87c549 100644 --- a/lib/archethic/contracts/interpreter/legacy/transaction_statements.ex +++ b/lib/archethic/contracts/interpreter/legacy/transaction_statements.ex @@ -46,6 +46,11 @@ defmodule Archethic.Contracts.Interpreter.Legacy.TransactionStatements do @spec add_uco_transfer(Transaction.t(), list()) :: Transaction.t() def add_uco_transfer(tx = %Transaction{}, args) when is_list(args) do %{"to" => to, "amount" => amount} = Enum.into(args, %{}) + + if amount <= 0 do + raise ArgumentError, message: "Contract used add_uco_transfer with an invalid amount" + end + to = UtilsInterpreter.get_address(to, :add_uco_transfer) update_in( @@ -90,6 +95,10 @@ defmodule Archethic.Contracts.Interpreter.Legacy.TransactionStatements do map_args = %{"to" => to, "amount" => amount, "token_address" => token_address} = Enum.into(args, %{}) + if amount <= 0 do + raise ArgumentError, message: "Contract used add_token_transfer with an invalid amount" + end + to = UtilsInterpreter.get_address(to, :add_token_transfer_to) token_address = diff --git a/test/archethic/contracts/interpreter/library/contract_test.exs b/test/archethic/contracts/interpreter/library/contract_test.exs index 6d8ef9d30..272b42135 100644 --- a/test/archethic/contracts/interpreter/library/contract_test.exs +++ b/test/archethic/contracts/interpreter/library/contract_test.exs @@ -188,6 +188,32 @@ defmodule Archethic.Contracts.Interpreter.Library.ContractTest do } } = sanitize_parse_execute(code) end + + test "should crash if the amount is 0" do + address = <<0::8, 0::8, :crypto.strong_rand_bytes(32)::binary>> + + code = ~s""" + actions triggered_by: transaction do + transfer = [to: "#{Base.encode16(address)}", amount: 0] + Contract.add_uco_transfer transfer + end + """ + + assert_raise(ArgumentError, fn -> sanitize_parse_execute(code) end) + end + + test "should crash if the amount is negative" do + address = <<0::8, 0::8, :crypto.strong_rand_bytes(32)::binary>> + + code = ~s""" + actions triggered_by: transaction do + transfer = [to: "#{Base.encode16(address)}", amount: -0.1] + Contract.add_uco_transfer transfer + end + """ + + assert_raise(ArgumentError, fn -> sanitize_parse_execute(code) end) + end end # ---------------------------------------- @@ -252,6 +278,34 @@ defmodule Archethic.Contracts.Interpreter.Library.ContractTest do } } = sanitize_parse_execute(code) end + + test "should crash if the amount is 0" do + address = <<0::8, 0::8, :crypto.strong_rand_bytes(32)::binary>> + token_address = <<0::8, 0::8, :crypto.strong_rand_bytes(32)::binary>> + + code = ~s""" + actions triggered_by: transaction do + transfer = [to: "#{Base.encode16(address)}", amount: 0, token_id: 1, token_address: "#{Base.encode16(token_address)}"] + Contract.add_token_transfer transfer + end + """ + + assert_raise(ArgumentError, fn -> sanitize_parse_execute(code) end) + end + + test "should crash if the amount is negative" do + address = <<0::8, 0::8, :crypto.strong_rand_bytes(32)::binary>> + token_address = <<0::8, 0::8, :crypto.strong_rand_bytes(32)::binary>> + + code = ~s""" + actions triggered_by: transaction do + transfer = [to: "#{Base.encode16(address)}", amount: -3, token_id: 1, token_address: "#{Base.encode16(token_address)}"] + Contract.add_token_transfer transfer + end + """ + + assert_raise(ArgumentError, fn -> sanitize_parse_execute(code) end) + end end # ---------------------------------------- diff --git a/test/archethic/contracts/interpreter_test.exs b/test/archethic/contracts/interpreter_test.exs index 6a08ca9a6..fe43abf18 100644 --- a/test/archethic/contracts/interpreter_test.exs +++ b/test/archethic/contracts/interpreter_test.exs @@ -359,6 +359,34 @@ defmodule Archethic.Contracts.InterpreterTest do data: %TransactionData{} } + assert match?( + {:error, :contract_failure}, + Interpreter.execute( + :transaction, + Contract.from_transaction!(contract_tx), + incoming_tx, + [incoming_tx] + ) + ) + + code = """ + @version 1 + condition inherit: [ + content: true + ] + + actions triggered_by: transaction do + Contract.add_uco_transfer amount: -1, to: "0000BFEF73346D20771614449D6BE9C705BF314067A0CF0ACBBF5E617EF5C978D0A1" + end + """ + + contract_tx = %Transaction{ + type: :contract, + data: %TransactionData{ + code: code + } + } + assert match?( {:error, :contract_failure}, Interpreter.execute( From 278bf2f63e86148aaa7ab8664144fa460f35aa9e Mon Sep 17 00:00:00 2001 From: Neylix Date: Thu, 4 May 2023 10:50:41 +0200 Subject: [PATCH 2/2] Fix rescue on all execute --- lib/archethic/contracts/interpreter.ex | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/archethic/contracts/interpreter.ex b/lib/archethic/contracts/interpreter.ex index efe2d36fe..15fb6e55e 100644 --- a/lib/archethic/contracts/interpreter.ex +++ b/lib/archethic/contracts/interpreter.ex @@ -148,6 +148,10 @@ defmodule Archethic.Contracts.Interpreter do opts ) end + rescue + _ -> + # it's ok to loose the error because it's user-code + {:error, :contract_failure} end @doc """ @@ -269,10 +273,6 @@ defmodule Archethic.Contracts.Interpreter do else {:error, :invalid_transaction_constraints} end - rescue - _ -> - # it's ok to loose the error because it's user-code - {:error, :contract_failure} end defp do_execute(