What If I told you there was a language with a path to abilities some may consider unnatural? Memory management you can do yourself, high gas efficiencies so your Dapp can on L2s and L1s seamlessly - all without having to sacrifice ease of use and readability.
Then allow me to introduce you to the world of Yul+.
Yul+ was developed by Fuel Labs, who needed a better way to write Ethereum’s closest thing to assembler - Yul. It has features that make it integrate easily with Solidity like function and topic signatures but keeps the efficiency of being so close to the EVM. Yul+’s main benefit comes from high-use contracts where small gains in efficiency will have their effects multiplied.
Yul itself is an intermediate language, which Solidity, Fe, and Vyper all compile to before they are transformed into bytecode. The difference here is that by writing the Yul yourself with enough experience, you can become more efficient than the compiler.
So why am I, a random smart contract developer, writing about it? Yul+ doesn’t have many learning resources for it, and the Yul documentation is literally a page that is barely mentioned in the documentation for Solidity.
I want to help spread Yul+ so more people can take advantage of its efficiency and the Ethereum Mainnet. This way, many sidechains can become less clogged up, allowing them to process more transactions.
So, now it’s time to get to work. I’ve built a plugin to allow drop-in use of Yul+ into your hardhat environment. Make sure your node.js versions and typescript versions are up to date (including npm). First, initialize a hardhat typescript project via:
npx hardhat init
Select:
> Create an advanced sample project that uses TypeScript
Add the following into your tsconfig file:
"allowJs": true,
"noImplicitAny": false
Clone the following repo hardhat-yul and place its contents into a folder named “Plugin,“ then place that folder into the root directory of your new hardhat directory. Then add the following line into your hardhatconfig.ts file:
import "./Plugin/src";
Next, from the root of your hardhat project directory, run:
npm install glob
npm install yulp
npm install solc
Next, delete the default smart contract and its accompanying test inside of the project, leaving you with a blank slate. If you encounter npm errors of things I forgot to mention that you need to install, please let me know on Github!
Now your entire environment is fully configured and set up!
In the contracts folder of your hardhat project, you will be writing your contracts.
Make a new file with the .yulp extension. Add the following code to your first contract, but note the contract name must be the same as the “object“ of the file.
object "SimpleStore" {
code {
datacopy(0, dataoffset("Runtime"), datasize("Runtime"))
return(0, datasize("Runtime"))
}
object "Runtime" {
code {
calldatacopy(0, 0, 36) // write calldata to memory
mstruct StoreCalldata( // Custom addressable calldata structure
sig: 4,
val: 32
)
switch StoreCalldata.sig(0) // select signature from memory (at position 0)
case sig"function store(uint256 val)" { // new signature method
sstore(0, StoreCalldata.val(0)) // sstore calldata value
log2(0, 0, topic"event Store(uint256 value)", StoreCalldata.val(0))
}
case sig"function get() returns (uint256)" {
mstore(100, sload(0))
return (100, 32)
}
}
}
}
The exact breakdown of what this contract does will be explained in the next tutorial.
Now, it’s time to make sure tests are working, so add the following javascript file to your “tests“ folder.
import { expect } from "chai";
import { ethers } from "hardhat";
describe("SimpleStore", function () {
it("SimpleStore", async function () {
const SimpleStore = await ethers.getContractFactory("SimpleStore");
const simplestore = await SimpleStore.deploy();
const tx = await simplestore.store(10);
const reciept = await tx.wait()
console.log(reciept.logs)
});
});
Then run the following:
npx hardhat compile
npx hardhat test
If this works, your test will pass! The following logs will be emitted:
[
{
topics: [
'0x69404ebde4a368ae324ed310becfefc3edfe9e5ebca74464e37ffffd8309a3c1',
'0x000000000000000000000000000000000000000000000000000000000000000a'
],
}
]
Topics will show the hexadecimal number 10 as log emitted, showing that the contract call to store the integer 10 worked!
Assuming all has worked so far, your development environment is set up, and you are ready to begin your Yul+ journey.