Closed mcintyre94 closed 2 years ago
@mcintyre94: Thank you for a detailed write-up! Much appreciated.
Thank you for opening this issue @mcintyre94, I like your sum-up on the different trade-offs. There could be a 3rd option: we could introduce a new kind of constructs in Clarinet, that would let us deal this specific scenario, but also others issues raised in the past.
We could tweak the parser or introduce a pre-processor in Clarinet, that would allow a construct like the following:
(contract-call? $MY_CONTRACT do-something)
In your chain config / deployment files, you would specify that for a given environment, you want $MY_CONTRACT to be remapped with a contract-id of your choice, and you could have different values depending on the environment (Test/Devnet/Testnet/Mainnet) that you'd like to target.
Curious to collect some takes on this approach.
Just to highlight a small change in behaviour, in Clarinet 0.3.0 contracts with these dependency issues don't get deployed at all in clarinet integrate
. So you'll no longer see a deploy transaction fail, it'll just be missing.
In case it helps anyone, I've written a Python script which will convert a Clarinet project ready to deploy w/ dev or mainnet dependencies and [[project.requirements]]
into one that will work with clarinet integrate
. Please make a git commit before running it so you can easily revert its changes if you try it out!
It will broadly do everything in option 2:
[[project.requirements]]
locally using the source code pulled from the dev/mainnetdepends_on
array for each updated contractNotes:
python3
, with requests
and toml
libraries installedIn your chain config / deployment files, you would specify that for a given environment, you want $MY_CONTRACT to be remapped with a contract-id of your choice, and you could have different values depending on the environment (Test/Devnet/Testnet/Mainnet) that you'd like to target.
I like this because it'd let you deploy to testnet and then mainnet without any code changes. Both solutions in the initial writeup would be limited to one or the other (in addition to local devnet), since you're hardcoding the address (which can only be on one or the other) into the contract.
Addressed in https://github.com/hirosystems/clarinet/pull/388
Moving discussion from Discord: https://discord.com/channels/621759717756370964/839633619261456444/973941248475938816
For anyone not familiar,
[[project.requirements]]
is a field in Clarinet.toml that allows 'pulling in' a testnet or mainnet contract that can be used as a dependency in contracts. For example, if we have the mainnet SIP-010 contract in that field:Then our contracts can reference the trait, eg.
(use-trait ft-trait 'SP3FBR2AGK5H9QBDH3EEN6DF8EK8JY7RX8QJ5SVTE.sip-010-trait-ft-standard.sip-010-trait)
Most clarinet commands (eg. check, console) will work with contracts using this feature. But
clarinet integrate
doesn't work correctly - any contract using arequirement
will fail to deploy. This is because in the local node there is no contract with eg.SP3FBR2AGK5H9QBDH3EEN6DF8EK8JY7RX8QJ5SVTE.sip-010-trait-ft-standard
. Currently the only way to work around this is to deploy the contract in the clarinet project, and modify the code manually to use the locally deployed one instead. This must of course be changed back to deploy, we can't run bothclarinet integrate
andclarinet contracts publish
on the same code.Ideally we want to run
clarinet integrate
on the code that will be deployed, so we want to be able to include eg.(use-trait ft-trait 'SP3FBR2AGK5H9QBDH3EEN6DF8EK8JY7RX8QJ5SVTE.sip-010-trait-ft-standard.sip-010-trait)
and have it work inclarinet integrate
.Two solutions were discussed:
The stacks node in
clarinet integrate
could be modified to allow deploying a contract as any address. Then if we haveSP3FBR2AGK5H9QBDH3EEN6DF8EK8JY7RX8QJ5SVTE.sip-010-trait-ft-standard
in requirements, then the local node would deploy that code asSP3FBR2AGK5H9QBDH3EEN6DF8EK8JY7RX8QJ5SVTE
, and our code using that would work correctlyWe could instead deploy the code from the requirements as the deployer. The contracts could then be transparently modified (as part of
clarinet integrate
and only in memory) to strip out the address and use the local deployment. Eg. we could replace(use-trait ft-trait 'SP3FBR2AGK5H9QBDH3EEN6DF8EK8JY7RX8QJ5SVTE.sip-010-trait-ft-standard.sip-010-trait)
with(use-trait ft-trait .sip-010-trait-ft-standard.sip-010-trait)
and then deploy.My not super well informed view of these is: