diff --git a/cairo/ethereum/cancun/state.cairo b/cairo/ethereum/cancun/state.cairo
index 4295defa6..52f29072f 100644
--- a/cairo/ethereum/cancun/state.cairo
+++ b/cairo/ethereum/cancun/state.cairo
@@ -2,7 +2,8 @@ from starkware.cairo.common.cairo_builtins import PoseidonBuiltin
 from starkware.cairo.common.dict_access import DictAccess
 from starkware.cairo.common.registers import get_fp_and_pc
 from starkware.cairo.common.math import assert_not_zero
-
+from starkware.cairo.common.uint256 import Uint256
+from src.utils.uint256 import uint256_add, uint256_sub
 from ethereum.cancun.fork_types import (
     Address,
     Account,
@@ -32,7 +33,7 @@ from ethereum.cancun.trie import (
 )
 from ethereum_types.bytes import Bytes, Bytes32
 from ethereum_types.numeric import U256, U256Struct, Bool, bool, Uint
-from ethereum.utils.numeric import is_zero
+from ethereum.utils.numeric import is_zero, U256_le, U256_sub, U256_add
 
 from src.utils.dict import hashdict_read, hashdict_write, hashdict_get, dict_new_empty
 
@@ -184,6 +185,27 @@ func set_account{poseidon_ptr: PoseidonBuiltin*, state: State}(
     return ();
 }
 
+func move_ether{range_check_ptr, poseidon_ptr: PoseidonBuiltin*, state: State}(
+    sender_address: Address, recipient_address: Address, amount: U256
+) {
+    alloc_locals;
+    let sender_account = get_account(sender_address);
+    let sender_balance = sender_account.value.balance;
+
+    let is_sender_balance_sufficient = U256_le(amount, sender_balance);
+    with_attr error_message("Sender has insufficient balance") {
+        assert is_sender_balance_sufficient.value = 1;
+    }
+
+    let new_sender_account_balance = U256_sub(sender_balance, amount);
+    set_account_balance(sender_address, new_sender_account_balance);
+
+    let recipient_account = get_account(recipient_address);
+    let new_recipient_account_balance = U256_add(recipient_account.value.balance, amount);
+    set_account_balance(recipient_address, new_recipient_account_balance);
+    return ();
+}
+
 func get_storage{poseidon_ptr: PoseidonBuiltin*, state: State}(
     address: Address, key: Bytes32
 ) -> U256 {
diff --git a/cairo/ethereum/utils/numeric.cairo b/cairo/ethereum/utils/numeric.cairo
index 3f4403a8f..86c5a35fd 100644
--- a/cairo/ethereum/utils/numeric.cairo
+++ b/cairo/ethereum/utils/numeric.cairo
@@ -5,7 +5,8 @@ from ethereum_types.bytes import Bytes32, Bytes32Struct, Bytes20
 from starkware.cairo.common.cairo_builtins import BitwiseBuiltin
 
 from starkware.cairo.common.math import split_felt
-from starkware.cairo.common.uint256 import word_reverse_endian
+from starkware.cairo.common.uint256 import word_reverse_endian, Uint256, uint256_le
+from src.utils.uint256 import uint256_add, uint256_sub
 
 func min{range_check_ptr}(a: felt, b: felt) -> felt {
     alloc_locals;
@@ -165,3 +166,34 @@ func U256_from_be_bytes20{range_check_ptr, bitwise_ptr: BitwiseBuiltin*}(bytes20
     tempvar res = U256(new U256Struct(low=low, high=high));
     return res;
 }
+
+// @dev Panics if overflow
+func U256_add{range_check_ptr}(a: U256, b: U256) -> U256 {
+    alloc_locals;
+    let (res, carry) = uint256_add([a.value], [b.value]);
+
+    with_attr error_message("OverflowError") {
+        assert carry = 0;
+    }
+
+    tempvar result = U256(new U256Struct(res.low, res.high));
+    return result;
+}
+
+// @dev Panics if underflow with OverflowError
+func U256_sub{range_check_ptr}(a: U256, b: U256) -> U256 {
+    alloc_locals;
+    let is_within_bounds = U256_le(b, a);
+    with_attr error_message("OverflowError") {
+        assert is_within_bounds.value = 1;
+    }
+    let (result) = uint256_sub([a.value], [b.value]);
+    tempvar res = U256(new U256Struct(result.low, result.high));
+    return res;
+}
+
+func U256_le{range_check_ptr}(a: U256, b: U256) -> bool {
+    let (result) = uint256_le([a.value], [b.value]);
+    tempvar res = bool(result);
+    return res;
+}
diff --git a/cairo/tests/ethereum/cancun/test_state.py b/cairo/tests/ethereum/cancun/test_state.py
index 15916b934..793e1a081 100644
--- a/cairo/tests/ethereum/cancun/test_state.py
+++ b/cairo/tests/ethereum/cancun/test_state.py
@@ -6,7 +6,7 @@
 from hypothesis import strategies as st
 from hypothesis.strategies import composite
 
-from ethereum.cancun.fork_types import Account
+from ethereum.cancun.fork_types import Account, Address
 from ethereum.cancun.state import (
     account_exists,
     account_exists_and_is_empty,
@@ -23,6 +23,7 @@
     is_account_alive,
     is_account_empty,
     mark_account_created,
+    move_ether,
     set_account,
     set_account_balance,
     set_code,
@@ -31,6 +32,7 @@
     touch_account,
 )
 from tests.utils.args_gen import State, TransientStorage
+from tests.utils.errors import strict_raises
 from tests.utils.strategies import address, bytes32, code, state, transient_storage
 
 
@@ -118,6 +120,24 @@ def test_set_account(self, cairo_run, data, account: Optional[Account]):
         set_account(state, address, account)
         assert state_cairo == state
 
+    @given(
+        data=state_and_address_and_optional_key(), recipient_address=address, amount=...
+    )
+    def test_move_ether(
+        self, cairo_run, data, recipient_address: Address, amount: U256
+    ):
+        state, sender_address = data
+        try:
+            state_cairo = cairo_run(
+                "move_ether", state, sender_address, recipient_address, amount
+            )
+        except Exception as cairo_error:
+            with strict_raises(type(cairo_error)):
+                move_ether(state, sender_address, recipient_address, amount)
+            return
+        move_ether(state, sender_address, recipient_address, amount)
+        assert state_cairo == state
+
     @given(data=state_and_address_and_optional_key())
     def test_destroy_account(self, cairo_run, data):
         state, address = data
diff --git a/cairo/tests/ethereum/utils/test_numeric.py b/cairo/tests/ethereum/utils/test_numeric.py
index 98d8c1fd1..56af7e77b 100644
--- a/cairo/tests/ethereum/utils/test_numeric.py
+++ b/cairo/tests/ethereum/utils/test_numeric.py
@@ -8,6 +8,7 @@
 from ethereum.cancun.fork_types import Address
 from ethereum.cancun.vm.gas import BLOB_GASPRICE_UPDATE_FRACTION, MIN_BLOB_GASPRICE
 from ethereum.utils.numeric import ceil32, taylor_exponential
+from tests.utils.errors import cairo_error
 from tests.utils.strategies import felt, uint128
 
 pytestmark = pytest.mark.python_vm
@@ -81,3 +82,30 @@ def test_U256__eq__(self, cairo_run, a: U256, b: U256):
     @given(address=...)
     def test_U256_from_be_bytes20(self, cairo_run, address: Address):
         assert U256.from_be_bytes(address) == cairo_run("U256_from_be_bytes20", address)
+
+    @given(a=..., b=...)
+    def test_U256_le(self, cairo_run, a: U256, b: U256):
+        assert (a <= b) == cairo_run("U256_le", a, b)
+
+    @given(a=..., b=...)
+    def test_U256_add(self, cairo_run, a: U256, b: U256):
+        try:
+            a + b
+        except Exception as e:
+            with cairo_error(str(e.__class__.__name__)):
+                cairo_result = cairo_run("U256_add", a, b)
+            return
+        cairo_result = cairo_run("U256_add", a, b)
+        assert cairo_result == a + b
+
+    @given(a=..., b=...)
+    def test_U256_sub(self, cairo_run, a: U256, b: U256):
+        try:
+            a - b
+        except Exception as e:
+            with cairo_error(str(e.__class__.__name__)):
+                cairo_result = cairo_run("U256_sub", a, b)
+            return
+
+        cairo_result = cairo_run("U256_sub", a, b)
+        assert cairo_result == a - b