LLL is back, baby! (It's all thanks to z80). Okay, so you want to use Dasy but you've settled on Foundry as your smart contract development environment. Fortunately, there's already a plugin — but how do you use it? Let's dive in!
These instructions assume we have both working Rust and Python installations.
Foundry is pretty self-explanatory:
$ curl -L https://foundry.paradigm.xyz | bash
Next, we'll need to install the Dasy compiler so that we can invoke it from Foundry (via its FFI facility). The Dasy documentation is pretty clear:
$ pipx install dasy
We need to set up a Forge project as per usual but also install our plugin that enables interoperability between the Dasy compiler and Foundry.
$ forge new foobar
$ cd foobar
$ forge install dasylang/foundry-dasy
Let's use z80's skunkworks example:
(defvar val :uint256)
(defn setValue [:uint256 val] :external
(set-self val))
(defn getValue [] :uint256 :external
(return self/val))
Unfortunately, tests still need to be written in Solidity. In order to achieve interoperability between the two languages, we'll have to make use of the DasyDeployer
library provided by the plugin. This works in much the same way as the Huff and Vyper equivalents, if you've used those before.
Essentially, we'll deploy our Dasy contract directly from disk, cast it to a shared Solidity interface, and then write tests as per usual.
// SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.15;
import "forge-std/Test.sol";
import "forge-std/console.sol";
import { DasyDeployer } from "foundry-dasy/DasyDeployer.sol";
contract SimpleStoreTest is Test {
/// @dev Address of the SimpleStore contract.
SimpleStore public foo;
/// @dev Setup the testing environment.
function setUp() public {
foo = SimpleStore(DasyDeployer.deploy("SimpleStore"));
}
/// @dev Ensure that you can set and get the value.
function testSetAndGetValue(uint256 value) public {
foo.setValue(value);
}
}
interface SimpleStore {
function setValue(uint256) external;
function getValue() external returns (uint256);
}
As of this step, our project structure should look something like this (I've ignored the build output and the dependencies for now):
$ tree .
.
├── dependencies.txt
├── foundry.toml
├── lib
├── README.md
├── script
├── src
│ └── SimpleStore.dasy
└── test
└── SimpleStore.t.sol
4 directories, 7 files
$ forge test
[⠰] Compiling...
No files changed, compilation skipped
Running 1 test for test/SimpleStore.t.sol:SimpleStoreTest
[PASS] testSetAndGetValue(uint256) (runs: 256, μ: 26477, ~: 27410)
Test result: ok. 1 passed; 0 failed; 0 skipped; finished in 930.25ms
Ran 1 test suites: 1 tests passed, 0 failed, 0 skipped (1 total tests)
At this stage, we have a working development environment that can both compile and test Dasy-language smart contracts.
I've recently made a few contributions to the Dasy plugin for Foundry in order to smooth things over with the developer experience and I'm happy with the current state of things. I'm very excited to deploy Dasy to production!