Skip to content

Commit

Permalink
Revert error (#80)
Browse files Browse the repository at this point in the history
* Define Python RevertError

* Update docstrings and remove empty page

* Extend test
  • Loading branch information
zombie-einstein authored Feb 16, 2024
1 parent 77d9eb9 commit 715208b
Show file tree
Hide file tree
Showing 8 changed files with 74 additions and 62 deletions.
1 change: 0 additions & 1 deletion docs/python/source/pages/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ API Reference
verbs.abi
verbs.batch_runner
verbs.sim
verbs.types
verbs.utils

The ``verbs.envs`` module also exposes simulation
Expand Down
3 changes: 2 additions & 1 deletion rust/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ use pyo3::prelude::*;
///
#[pymodule]
#[pyo3(name = "envs")]
fn verbs(_py: Python<'_>, m: &PyModule) -> PyResult<()> {
fn verbs(py: Python<'_>, m: &PyModule) -> PyResult<()> {
m.add_class::<sim::EmptyEnv>()?;
m.add_class::<sim::ForkEnv>()?;
m.add("RevertError", py.get_type::<types::PyRevertError>())?;
Ok(())
}
12 changes: 6 additions & 6 deletions rust/src/sim/empty_env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ impl EmptyEnv {
///
/// Raises
/// ------
/// RevertError
/// verbs.envs.RevertError
/// Raises an exception if the transaction is reverted.
///
pub fn call<'a>(
Expand All @@ -272,13 +272,13 @@ impl EmptyEnv {
contract_address: PyAddress,
encoded_args: Vec<u8>,
value: u128,
) -> Result<PyExecutionResult, PyRevertError> {
) -> PyResult<PyExecutionResult> {
let result = self
.0
.call(py, sender, contract_address, encoded_args, value);
match result {
Ok(x) => Ok(x),
Err(x) => Err(x.into()),
Err(x) => Err(PyRevertError::new_err(x.output)),
}
}

Expand Down Expand Up @@ -307,7 +307,7 @@ impl EmptyEnv {
///
/// Raises
/// ------
/// RevertError
/// verbs.envs.RevertError
/// Raises an exception if the transaction is reverted.
///
pub fn execute<'a>(
Expand All @@ -317,13 +317,13 @@ impl EmptyEnv {
contract_address: PyAddress,
encoded_args: Vec<u8>,
value: u128,
) -> Result<PyExecutionResult, PyRevertError> {
) -> PyResult<PyExecutionResult> {
let result = self
.0
.execute(py, sender, contract_address, encoded_args, value);
match result {
Ok(x) => Ok(x),
Err(x) => Err(x.into()),
Err(x) => Err(PyRevertError::new_err(x.output)),
}
}
}
12 changes: 6 additions & 6 deletions rust/src/sim/fork_env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ impl ForkEnv {
///
/// Raises
/// ------
/// RevertError
/// verbs.envs.RevertError
/// Raises an exception if the transaction is reverted.
///
pub fn call<'a>(
Expand All @@ -308,13 +308,13 @@ impl ForkEnv {
contract_address: PyAddress,
encoded_args: Vec<u8>,
value: u128,
) -> Result<PyExecutionResult, PyRevertError> {
) -> PyResult<PyExecutionResult> {
let result = self
.0
.call(py, sender, contract_address, encoded_args, value);
match result {
Ok(x) => Ok(x),
Err(x) => Err(x.into()),
Err(x) => Err(PyRevertError::new_err(x.output)),
}
}

Expand Down Expand Up @@ -343,7 +343,7 @@ impl ForkEnv {
///
/// Raises
/// ------
/// RevertError
/// verbs.envs.RevertError
/// Raises an exception if the transaction is reverted.
///
pub fn execute<'a>(
Expand All @@ -353,13 +353,13 @@ impl ForkEnv {
contract_address: PyAddress,
encoded_args: Vec<u8>,
value: u128,
) -> Result<PyExecutionResult, PyRevertError> {
) -> PyResult<PyExecutionResult> {
let result = self
.0
.execute(py, sender, contract_address, encoded_args, value);
match result {
Ok(x) => Ok(x),
Err(x) => Err(x.into()),
Err(x) => Err(PyRevertError::new_err(x.output)),
}
}
}
32 changes: 4 additions & 28 deletions rust/src/types.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
use alloy_primitives::{Address, Bytes};
use pyo3::exceptions::PyException;
use pyo3::types::PyBytes;
use pyo3::{PyErr, Python};
use pyo3::{create_exception, Python};
use revm::primitives::ExecutionResult;
use rust_sim::{contract::Event, network::RevertError};
use std::{borrow::Cow, fmt};
use std::borrow::Cow;

create_exception!(envs, PyRevertError, PyException);

pub type PyAddress<'a> = Cow<'a, [u8]>;

Expand Down Expand Up @@ -57,29 +59,3 @@ pub fn result_to_py(
Err(x) => Err(x.clone()),
}
}

pub struct PyRevertError {
reason: Option<String>,
}

impl fmt::Display for PyRevertError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let reason = match &self.reason {
Some(x) => x.as_str(),
None => "No output",
};
write!(f, "{}", reason)
}
}

impl std::convert::From<PyRevertError> for PyErr {
fn from(err: PyRevertError) -> PyErr {
PyException::new_err(err.to_string())
}
}

impl std::convert::From<RevertError> for PyRevertError {
fn from(err: RevertError) -> PyRevertError {
PyRevertError { reason: err.output }
}
}
39 changes: 23 additions & 16 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,27 +9,34 @@
@pytest.fixture
def bytecode():
hex = (
"0x608060405234801561001057600080fd5b5060405161026f3803806102"
"6f8339818101604052810190610032919061007a565b8060008190555050"
"0x608060405234801561001057600080fd5b506040516103313803806103"
"318339818101604052810190610032919061007a565b8060008190555050"
"6100a7565b600080fd5b6000819050919050565b61005781610044565b81"
"1461006257600080fd5b50565b6000815190506100748161004e565b9291"
"5050565b6000602082840312156100905761008f61003f565b5b60006100"
"9e84828501610065565b91505092915050565b6101b9806100b660003960"
"9e84828501610065565b91505092915050565b61027b806100b660003960"
"00f3fe608060405234801561001057600080fd5b50600436106100365760"
"003560e01c8063209652551461003b5780635093dc7d14610059575b6000"
"80fd5b610043610075565b60405161005091906100e1565b604051809103"
"90f35b610073600480360381019061006e919061012d565b61007e565b00"
"5b60008054905090565b600080549050816000819055507fb8ba75888072"
"4160775cc09f9aa6f15e3d6be6aed023b548a74a72981f806f6381836040"
"516100bc92919061015a565b60405180910390a15050565b600081905091"
"9050565b6100db816100c8565b82525050565b60006020820190506100f6"
"60008301846100d2565b92915050565b600080fd5b61010a816100c8565b"
"811461011557600080fd5b50565b60008135905061012781610101565b92"
"915050565b600060208284031215610143576101426100fc565b5b600061"
"015184828501610118565b91505092915050565b60006040820190506101"
"6f60008301856100d2565b61017c60208301846100d2565b939250505056"
"fea264697066735822122023e51761b7f66dc61568d8bcae2f6f8877a5c3"
"f186e8ebb9c89260d547e2a8f864736f6c634300080a0033"
"80fd5b610043610075565b6040516100509190610126565b604051809103"
"90f35b610073600480360381019061006e9190610172565b61007e565b00"
"5b60008054905090565b6103e88113156100c3576040517f08c379a00000"
"000000000000000000000000000000000000000000000000000081526004"
"016100ba906101fc565b60405180910390fd5b6000805490508160008190"
"55507fb8ba758880724160775cc09f9aa6f15e3d6be6aed023b548a74a72"
"981f806f63818360405161010192919061021c565b60405180910390a150"
"50565b6000819050919050565b6101208161010d565b82525050565b6000"
"60208201905061013b6000830184610117565b92915050565b600080fd5b"
"61014f8161010d565b811461015a57600080fd5b50565b60008135905061"
"016c81610146565b92915050565b60006020828403121561018857610187"
"610141565b5b60006101968482850161015d565b91505092915050565b60"
"0082825260208201905092915050565b7f2056616c7565206d7573742062"
"65206c657373207468616e2031303030000000600082015250565b600061"
"01e6601d8361019f565b91506101f1826101b0565b602082019050919050"
"565b60006020820190508181036000830152610215816101d9565b905091"
"9050565b60006040820190506102316000830185610117565b61023e6020"
"830184610117565b939250505056fea2646970667358221220a3de9113ee"
"b3f4094e585e8eb6de3c4a72bf5615c5cdba826ea9d63366251ce464736f"
"6c634300080a0033"
)

return utils.hex_to_bytes(hex)
Expand Down
11 changes: 8 additions & 3 deletions tests/simple_contract.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,13 @@ contract Contract {
}

function setValue(int256 x) public {
int256 old_x = _x;
_x = x;
emit ValueUpdated(old_x, x);
if( x > 1000){
revert(" Value must be less than 1000");
}
else{
int256 old_x = _x;
_x = x;
emit ValueUpdated(old_x, x);
}
}
}
26 changes: 25 additions & 1 deletion tests/test_env.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
from verbs import abi, utils
import pytest

from verbs import abi, envs, utils

INITIAL_VALUE = 101

Expand Down Expand Up @@ -56,3 +58,25 @@ def test_sim_update(env, bytecode, constructor_args, test_abi):
# Get new value after block update
result_2, _, _ = a.getValue.call(env, admin, address, [])
assert result_2[0] == 202


def test_revert_exception(env, bytecode, constructor_args, test_abi):

env.create_account(utils.ZERO_ADDRESS, int(1e19))

a = abi.get_abi("ABI", test_abi)

address = env.deploy_contract(
utils.ZERO_ADDRESS, "test_contract", bytecode + constructor_args
)

# Should be fine
a.setValue.execute(env, utils.ZERO_ADDRESS, address, [500])

# Should revert as value is > 1000
with pytest.raises(envs.RevertError):
a.setValue.execute(env, utils.ZERO_ADDRESS, address, [1001])

# Should also raise from a call
with pytest.raises(envs.RevertError):
a.setValue.call(env, utils.ZERO_ADDRESS, address, [1001])

0 comments on commit 715208b

Please sign in to comment.