owned this note
owned this note
Published
Linked with GitHub
# Yul+
## Background
Put in the links to the old issues. Mention the call we had.
## Features
### Constructor/Runtime objects
#### Current
```
object "Contract1" {
code {
size := datasize("runtime")
offset := allocate(size)
datacopy(offset, dataoffset("runtime"), size)
return(offset, size)
}
object "runtime" {
code {
}
}
}
```
#### Nicks Code Example
```
code Nick {
constructor {
// some code here...
}
// run time here.
// rest of code...
}
code John is Nick { // this makes it extensible
}
```
#### Alex's proposal
```
object "Contract" {
const something := 0xaa
function name() {}
constructor {
name(something)
return_runtime()
size := datasize("runtime")
offset := allocate(size)
datacopy(offset, dataoffset("runtime"), size)
return(offset, size)
}
runtime {
name(something)
}
deposit_holder {
// ENS deposit holder
}
}
```
Questions:
1. In yul are non-referenced objects dropped?
2. Support sharing functions between objects.
### Explicit constants
...
### Enums
```
enum Color {
Red,
Blue,
Green
}
```
```
function x() {
let y := Color.Red
}
```
### Structured memory
```
mstruct Color {
Red: 4,
Blue: 20,
Green: 32
}
Color.Red // 4
Color(32).Red // slice(mload(32 + 0), 4)
## Use Case (Proof in Calldata)
copycallata(...)
# Memory... Complex Structure at Memory Position 0: 0xaabbcccc
let aVal := slice(mload(0 + 0), 1) // 0xaa
let bVal := slice(mload(0 + 1), 1) // 0xbb
let cVal := slice(mload(0 + 2), 2) // 0xcccc
```
```
mstruct Color {
Red: 4,
Blue: 20,
Green: 32 // this is max slice size
}
Color.Red -> 0
Color.Red.length -> 4
enum ColorOffsets {
}
enum ColorLengths {
}
function Color(mem_offset, field_identifier) -> ret {
let tmp := alloc(datasize(identifier))
memcpy(tmp, dataoffset(mystruct, identifier), datasize(identifier))
ret := mload(tmp)
}
//dataoffset(Color.Blue)
//datasize(Color.Blue)
//datacopy()
//memcpy(destination, source, length)
let mystruct := alloc(calldatasize())
calldatacopy(mystruct, 0, calldatasize())
memcpy(aVal, dataoffset(mystruct, Color.Blue), datasize(Color.Blue))
// syntactic sugar for the above
Color(0).Blue // slice(0 + 0, 4) -> 0xbb
Color(45, {
Red: 0xaa,
Blue: 0xbb,
Green: 0xcccc,
})
Color(0, Color.Blue) // will jump through color red
Color(0, Blue) // will jump through color red
let color := Color(0)
```
### Imports
#### Nicks Example
./ecrecover.yul
```
{
const something := 0xaa
// cant do this let nick := 0xaa
function ecrecover(hash, signature) {
return ...
}
// Assert True or Invalid Proof
function assert(arg, errorCode) {
if lt(arg, 1) {
// Set Error Code In memory
mstore(mul32(1), errorCode)
// Revert and Return Error Code
revert(mul32(1), mul32(1))
// Just incase we add a stop
stop()
}
}
function slice(position, length) -> result {
if gt(length, 32) { revert(0, 0) } // protect against overflow
result := div(mload(position), exp(2, safeSub(256, safeMul(length, 8))))
}
}
```
./Contract.yul
```
import { ecrecover, assert, something } from "./ecrecover.yul"
object "Contract" {
constructor {
assert(0xaa, something)
}
runtime {
ecrecover(0xaa, something)
assert(something, 0xbb)
}
}
```
#### Alex's proposal
Hint: mixins
```
runtime {
include ecrecover
include "ecrecover.yul"
}
```