
Product
Introducing Module Reachability: Focus on the Vulnerabilities That Matter
Module Reachability filters out unreachable CVEs so you can focus on vulnerabilities that actually matter to your application.
A low-level, highly efficient extension to Yul, an intermediate smart-contract language for the Ethereum Virtual Machine.
mstruct
)enum
)const
)sig"function ..."
, topic"event ...
)true
, false
)mslice
and require
)npm install -g yulp
const yulp = require('../index');
const source = yulp.compile(`
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)
}
}
}
}
`);
console.log(yulp.print(source.results));
Here we have a fully featured enum
identifier which acts as a constant.
object "contract" {
code {
enum Colors (
Red,
Blue,
Green
)
log1(0, 0, Colors.Green) // logs 2 as a topic
}
}
const
will define a let
variable value that cannot be re-assigned.
object "contract" {
code {
const firstVar := 0xaa
const someOther := 1
}
}
mslice(position, length)
will return a 1-32 byte value from memory.
object "contract" {
code {
mstore(30, 0xaaaa)
log1(0, 0, mslice(30, 2)) // will log 0xaaaa
}
}
true
and false
are added and equate to values 0x01
and 0x00
.
object "contract" {
code {
mstore(30, true)
log1(0, 0, mload(30)) // will log 0x01
}
}
mstore
can now be used as a proxy method
object "contract" {
code {
mstore(30, 1, 2, 3, 4)
/*
mstore(30, 1)
mstore(add(30, 32), 2)
mstore(add(30, 64), 3)
mstore(add(30, 96), 4)
*/
}
}
lte
, gte
, neq
can now be used.
if and(lte(1, 10), gte(5, 2)) {
let k := neq(0, 1)
}
MAX_UINT
literal is now available (i.e. uint(-1)
)
if lt(v, MAX_UINT) {
let k := 1
}
sig" [ method abi ] "
will equate to a 4 byte method signature hex value
topic" [ event abi definition ] "
will equate to the 32 byte topic hash
object "contract" {
code {
const storeSig := sig"function store(uint256 val)"
const eventSig := topic"event Store (uint256 indexed val)"
log1(0, 0, storeSig) // will log 0x6057361d
log1(0, 0, eventSig) // will log 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef
}
}
Memory structures enable better handling of pre-existing in-memory structures.
mstruct Identifier ( [ property, ... ] )
A structure property is defined by an identifier and length specifier (i.e. blockProducer:32
) where the identifier is blockProducer
and the length is 32 bytes
.
In-memory array like structures are defined using a name.length
property, followed by a name:[array item size]
property.
Note, mstruct
properties allow for data chunk sizes up to 32 bytes only.
object "Utils" {
code {
const Size := 1
function someMethod() -> {}
}
}
object "SimpleStore" is "Utils" {
code {
mstore(0, Size)
someMethod()
}
}
We now support basic file system usage, we don't support local path resolution just yet.
The fs
object is simply supplied at compile
: yulp.compile(source, fs)
.
import "./Utils.yulp"
object "SimpleStore" is "Utils" {
...
}
A new experimental (post v0.0.7) feature is the error"some message"
literal.
This simply utf8 encodes the message to bytes, keccak256 hashes it and returns the first 4 bytes as an error identifier.
The compiler will return an errors
property ({ [4 byte idenfitier]: [error message], ... }
).
object "contract" {
code {
// example structure in memory of a BlockHeader starting at mem. position 400
mstore(400, 0xaa) // block producer
mstore(432, 0xbb) // previous block hash
mstore(464, 0xcc) // block height
mstore(496, 0x03) // length of anotherArray (i.e. 3 array items)
mstore(554, 0xaaaabbbbcccc) // array with 3 elements, 0xaaaa, 0xbbbb, 0xcccc
mstore(560, 0xdd) // Ethereum block number
mstore(592, 0x01) // transaction roots array length
mstore(652, 0xffffffff) // transaction roots, one 4 byte item 0xffffffff
mstruct BlockHeader (
blockProducer: 32,
previousBlockHash: 32,
blockHeight: 32,
anotherArray.length: 32,
anotherArray: [2],
ethereumBlockNumber: 32,
roots.length: 32,
roots: [4]
)
BlockHeader.blockProducer(400) // will return 0xaa
BlockHeader.blockProducer.size() // will return 32
BlockHeader.blockHeight(400) // will return block height 0xcc
BlockHeader.blockHeight.offset(400) // will return pos + length
BlockHeader.blockHeight.position(400) // will return pos
BlockHeader.blockHeight.size() // 32
BlockHeader.blockHeight.index() // 2
BlockHeader.blockHeight.keccak256(500) // keccak256 hash the block height
BlockHeader.anotherArray(400, 2) // will return anotherArray item 0xcccc
BlockHeader.size(400) // will return the size of the entire struct
BlockHeader.offset(400) // will return entire offset position of the struct pos + length
BlockHeader.keccak256(400) // keccak256 hash the entire block header
}
}
There is always a lot of work to do, and will have many rules to maintain. So please help out in any way that you can:
yulp
better, and pull requests to show us how your idea works.We communicate via issues and pull requests.
Please consider donating if you think Yul+ is helpful to you or that my work is valuable. We are happy if you can help us buy a cup of coffee. ❤️
Or just send us some Dai, USDC or Ether:
0x3e947a271a37Ae7B59921c57be0a3246Ee0d887C Etherscan
mstruct BasicRecursiveStructures ( // better structure description
block: BlockHeader,
root: RootHeader,
proof: MerkleProof,
leaf: TransactionLeaf,
token: 32
)
mstruct SwitchStatements ( // special switch case
data.switch: 1, // switch 0, 1, 2 for options below
data: [InputUTXO,InputHTLC,TransactionDeposit]
)
mstruct FixedLengthArrays ( // special switch case
someArr: (7)[32],
)
FAQs
A low-level highly-efficient language for the Ethereum Virtual Machine.
The npm package yulp receives a total of 3,337 weekly downloads. As such, yulp popularity was classified as popular.
We found that yulp demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Product
Module Reachability filters out unreachable CVEs so you can focus on vulnerabilities that actually matter to your application.
Company News
Socket is bringing best-in-class reachability analysis into the platform — cutting false positives, accelerating triage, and cementing our place as the leader in software supply chain security.
Product
Socket is introducing a new way to organize repositories and apply repository-specific security policies.