-
Notifications
You must be signed in to change notification settings - Fork 23
Description
Related to #314
We’ve encountered a persistent issue with the zinkc dispatcher
when using the #[derive(Storage)]
macro (introduced in PR #314, resolving #288) for unified structs with multiple fields. While single-field structs (e.g., getter.rs
) work correctly, multi-field structs (e.g., contract.rs
) exhibit runtime dispatch failures, preventing external method calls from functioning as expected. This blocks core functionality like transfer()
and approve()
in ERC20
contracts, critical for practical use.
For example:
getter.rs
(Single-field):
Struct: Getter { value: Bytes32 }
Method: #[zink::external] get_value(&self) -> Bytes32
Result: Test passes—get_value()
returns the stored value.
let value_info = evm.calldata(&contract.encode(&[b"get_value()".to_vec()])?).call(address)?;
assert_eq!(value_info.ret, value_array.to_vec(), "Getter failed");
contract.rs
(Multi-field, ERC20
):
Struct:
ERC20 {
name: Bytes32,
symbol: Bytes32,
total_supply: U256,
balances: Mapping<Address, U256>,
allowances: DoubleKeyMapping<Address, Address, U256>
}
Methods: Multiple #[zink::external]
(e.g., init
, name
, transfer
) and internal #[no_mangle]
(e.g., _transfer
)
Result: Storage tests pass, runtime calls fail:
name()
reverts with "Empty from address" from _transfer
.
// Failed runtime call
let name_ret = evm.calldata(&contract.encode(&[b"name()".to_vec()])?).call(address)?;
assert_eq!(name_ret.ret, name_array.to_vec(), "Name mismatch: {name_ret:?}");
// Output: revert: Some("Empty from address")
Cause: Dispatcher misroutes name() (0x06fdde03) to _transfer (0xa9059cbb).
Tracking List for Resolution
- Reliable Runtime Calls: return correct storage values in multi-field structs.
- ERC20 Functionality: Allow transfer(), approve(), and transfer_from() in contract.rs and erc20.rs to execute without reverts.