-
Notifications
You must be signed in to change notification settings - Fork 710
Description
Describe the bug
The (use-trait trait-alias contract.trait-name)
statement makes trait-name
available locally under name trait-alias
.
However, if this contract also contains a (define-trait trait-name (...))
, then trait-alias
will be overridden to point to the current contract's version of trait-name
instead of the trait definition contained in the contract pointed to by use-trait
.
Let's see an example.
Clarity will accept this first contract:
a-trait.clar
(define-trait a (
(do-it () (response bool bool))
))
However, the contract below is rejected:
use-a-trait-1.clar
(use-trait a-alias 'SP8CW062DS1XAZJJXWKSM9EMMDD51BRVFMY8MBX6.a-trait.a)
(define-trait a (
(do-that () (response bool bool))
))
(define-public (call-do-it (a-contract <a-alias>))
(contract-call? a-contract do-it)
)
It returns the error:
**{"error":{"initialization":"TraitMethodUnknown(\"a\", \"do-it\")
Near:
[SymbolicExpression { expr: List([SymbolicExpression { expr: Atom(ClarityName(\"contract-call?\")), id: 13, span: Span { start_line: 4, start_column: 4, end_line: 4, end_column: 17 } }, SymbolicExpression { expr: Atom(ClarityName(\"a-contract\")), id: 14, span: Span { start_line: 4, start_column: 19, end_line: 4, end_column: 28 } }, SymbolicExpression { expr: Atom(ClarityName(\"do-it\")), id: 15, span: Span { start_line: 4, start_column: 30, end_line: 4, end_column: 34 } }]), id: 12, span: Span { start_line: 4, start_column: 3, end_line: 4, end_column: 35 } }]"}}**
On the other hand, the following contract is accepted:
use-a-trait-2.clar
(use-trait a-alias 'SP8CW062DS1XAZJJXWKSM9EMMDD51BRVFMY8MBX6.a-trait.a)
(define-trait a (
(do-that () (response bool bool))
))
;; trait name a points to current version of a trait; seems OK
(define-public (call-do-that-2 (a-contract <a>))
(contract-call? a-contract do-that)
)
;; trait alias from use statement _also_ points to current version of a trait; seems wrong
(define-public (call-do-that (a-contract <a-alias>))
(contract-call? a-contract do-that)
)
Steps To Reproduce
If the contract files are named as above, then the CLI invocation to test would be:
clarity-cli initialize initial-allocations.json vm-state.db
clarity-cli launch SP8CW062DS1XAZJJXWKSM9EMMDD51BRVFMY8MBX6.a-trait a-trait.clar vm-state.db
clarity-cli launch SP8CW062DS1XAZJJXWKSM9EMMDD51BRVFMY8MBX6.use-a-trait-1 use-a-trait-1.clar vm-state.db
clarity-cli launch SP8CW062DS1XAZJJXWKSM9EMMDD51BRVFMY8MBX6.use-a-trait-2 use-a-trait-2.clar vm-state.db
Expected behavior
So, firstly, I'm not sure if it makes sense to allow a contract to do:
(use-trait a-alias contract-name.a)
(define-trait a (...))
Since this makes the rules for transitive imports via use-trait
a bit more complex (i.e. there is a kind of name shadowing in the transitive trait use process where clarity seems to frown upon name shadowing) since doing the following in a later contract:
(use-trait a-alias-2 SP8CW062DS1XAZJJXWKSM9EMMDD51BRVFMY8MBX6.use-a-trait-2.a)
will get me use-a-trait-2
's version of trait a
instead of the original.
However, if this is to be allowed, then I expect that all uses of a-alias
inside the contract use-a-trait-1
and use-a-trait-2
should point to the trait definition imported by use-trait
from a-trait
and not to the local definition of trait a
.
Environment (please complete the following information):
- OS: WSL 2 Arch Linux
- Rust version: 1.61.0
- Clarity version: https://github.com/stacks-network/stacks-blockchain/tree/08c163bab484954b3934515ee7bf60848f52ed4a
Additional context
N/A