Skip to content

Commit 62ab3f0

Browse files
authored
feat: transaction revert + nondeterministic addresses (#62)
This pr adds a few important features: - No randomness in address generation anymore. Addresses will be derived from a string representation of the argument name. And the argument name is guarantied to be unique by rust - State of the contract (on-chain data, events) and account balances can be reverted when call fails. Works even in external multi call cases, when just a single contract reverted transaction, but others handled error and finished transaction. - String representation of address linked to string tag (argument name) that can be used to create better error messages. Resolves #32, resolves #27
1 parent 2dde3ad commit 62ab3f0

File tree

7 files changed

+774
-74
lines changed

7 files changed

+774
-74
lines changed

CHANGELOG.md

+8
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99

1010
### Added
1111

12+
- Fixed bug with invalid size of return data from external call #68
13+
- No randomness in address generation anymore.
14+
Addresses will be derived from a string representation of the argument name #62
15+
- State of the contract (on-chain data, events) and account balances can be
16+
reverted when call fails #62
17+
- String representation of address linked to a string tag (argument name),
18+
that is used for error message formatting #62
19+
1220
### Changed (Breaking)
1321

1422
## [0.5.0] - 2025-03-05

crates/motsu-proc/src/test.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,9 @@ pub(crate) fn test(_attr: &TokenStream, input: TokenStream) -> TokenStream {
4040
});
4141

4242
// Collect argument initializations.
43-
let arg_inits = arg_binding_and_ty.iter().map(|(_arg_binding, arg_ty)| {
43+
let arg_inits = arg_binding_and_ty.iter().map(|(arg_binding, arg_ty)| {
4444
quote! {
45-
<#arg_ty>::random()
45+
<#arg_ty as motsu::prelude::FromTag>::from_tag(stringify!(#arg_binding))
4646
}
4747
});
4848

crates/motsu/README.md

+35-3
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ mod tests {
3333
}
3434
```
3535

36+
### Sender and Value
37+
3638
Function `Contract::sender()` is necessary to trigger call
3739
to a contract, and should accept an `Account` or `Address` as an argument.
3840

@@ -65,9 +67,11 @@ fn pay_three_proxies(proxy: Contract<Proxy>, alice: Account) {
6567
}
6668
```
6769

70+
### External Calls
71+
6872
Multiple external calls are supported in Motsu.
6973
Assuming `Proxy` is a contract that exposes (`#[public]`) function `call_proxy`,
70-
where it adds `one` to the passed argument and calls next `Proxy` contract
74+
where it adds `one` to the passed argument and calls next `Proxy` contract
7175
at the address provided during initialization.
7276
The following test case can emulate a call chain of three `Proxy` contracts:
7377

@@ -98,11 +102,39 @@ fn call_three_proxies(
98102
}
99103
```
100104

101-
It is possible to check emitted events by specific contract with
105+
### Checking Events
106+
107+
It is possible to check emitted events by specific contract with
102108
`Contract::emitted` method.
103-
And assert with `Contract::assert_emitted` that will print all matching
109+
And assert with `Contract::assert_emitted` that will print all matching
104110
events in case of failed assertion.
105111

112+
### Transaction Revert
113+
114+
To revert a transaction in case of `Result::Err`, you should call one of
115+
the following functions:
116+
117+
- `ResultExt::motsu_unwrap`
118+
- `ResultExt::motsu_unwrap_err`
119+
- `ResultExt::motsu_expect`
120+
- `ResultExt::motsu_expect_err`
121+
- `ResultExt::motsu_res`
122+
123+
```rust, ignore
124+
const FOUR: U256 = uint!(4_U256);
125+
126+
// If the argument is `FOUR`, the call should revert.
127+
let err = proxy.sender(alice).try_call_proxy(FOUR).motsu_unwrap_err();
128+
assert!(matches!(err, Error::ProxyError(_)));
129+
```
130+
131+
Otherwise, the state of the contract including persistent storage, balances
132+
and emitted events won't be reverted in case of `Result::Err`.
133+
134+
Panics in contract code are not handled as a revert and will fail the test.
135+
136+
### Notes
137+
106138
Annotating a test function that accepts no parameters will make
107139
`#[motsu::test]` behave the same as `#[test]`.
108140

0 commit comments

Comments
 (0)