Skip to content

Commit

Permalink
piecrust: use empty constructor arguments by default
Browse files Browse the repository at this point in the history
Previously we were erroring out when providing no arguments for a
constructor that takes no argument. This is undesirable since downstream
does not necessarily know that the contract they deploy has a constructor.

A contract that is provided an argument that it doesn't expect will
still error at deploy time, during execution of the constructor.

Resolves #316
  • Loading branch information
Eduardo Leegwater Simões committed Feb 22, 2024
1 parent 56ae082 commit 0dc4c06
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 24 deletions.
2 changes: 2 additions & 0 deletions piecrust/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Changed

- Use empty constructor arguments by default [#316]
- Upgrade `dusk-wasmtime` to version `18`

## [0.16.0] - 2024-02-14
Expand Down Expand Up @@ -366,6 +367,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
<!-- ISSUES -->
[#325]: https://github.com/dusk-network/piecrust/issues/325
[#324]: https://github.com/dusk-network/piecrust/issues/324
[#316]: https://github.com/dusk-network/piecrust/issues/316
[#301]: https://github.com/dusk-network/piecrust/issues/313
[#301]: https://github.com/dusk-network/piecrust/issues/301
[#296]: https://github.com/dusk-network/piecrust/issues/296
Expand Down
23 changes: 7 additions & 16 deletions piecrust/src/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -289,22 +289,13 @@ impl Session {
let instance =
self.instance(&contract_id).expect("instance should exist");

let has_init = instance.is_function_exported(INIT_METHOD);
if has_init && arg.is_none() {
return Err(InitalizationError(
"Contract has constructor but no argument was provided"
.into(),
));
}

if let Some(arg) = arg {
if !has_init {
return Err(InitalizationError(
"Argument was provided but contract has no constructor"
.into(),
));
}

if instance.is_function_exported(INIT_METHOD) {
// If no argument was provided, we call the constructor anyway,
// but with an empty argument. The alternative is to panic, but
// that assumes that the caller of `deploy` knows that the
// contract has a constructor in the first place, which might
// not be the case, such as when ingesting untrusted bytecode.
let arg = arg.unwrap_or_default();
self.call_inner(contract_id, INIT_METHOD, arg, gas_limit)?;
}

Expand Down
16 changes: 8 additions & 8 deletions piecrust/tests/constructor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,20 +73,20 @@ fn constructor() -> Result<(), Error> {
}

#[test]
fn missing_init() -> Result<(), Error> {
fn empty_constructor_argument() -> Result<(), Error> {
let vm = VM::ephemeral()?;

let mut session = vm.session(SessionData::builder())?;

let result = session.deploy(
contract_bytecode!("counter"),
ContractData::builder(OWNER).constructor_arg(&0xabu8),
let id = session.deploy(
contract_bytecode!("empty_constructor"),
ContractData::builder(OWNER),
LIMIT,
);
)?;

assert!(
result.is_err(),
"deploy with data when the 'init' method is not exported should fail with an error"
assert_eq!(
session.call::<_, u8>(id, "read_value", &(), LIMIT)?.data,
0x10
);

Ok(())
Expand Down

0 comments on commit 0dc4c06

Please sign in to comment.