Releases: ethereum/fe
v0.16.0-alpha "Pyrope"
0.16.0-alpha (2022-05-05)
WARNING: All Fe releases are alpha releases and only meant to share the development progress with developers and enthusiasts. It is NOT yet ready for production usage.
Features
- Change static function call syntax from
Bar.foo()
toBar::foo()
(#241) - Added support for retrieving the base fee via
ctx.base_fee()
(#503)
Bugfixes
- Resolve functions on structs via path (e.g.
bi::ba::bums()
) (#241)
v0.15.0-alpha "Onyx"
WARNING: All Fe releases are alpha releases and only meant to share the development progress with developers and enthusiasts. It is NOT yet ready for production usage.
0.15.0-alpha "Onyx" (2022-04-04)
Features
-
Labels are now required on function arguments. Labels can be omitted if the
argument is a variable with a name that matches the label, or if the function
definition specifies that an argument should have no label. Functions often take
several arguments of the same type; compiler-checked labels can help prevent
accidentally providing arguments in the wrong order.Example:
contract CoolCoin: balance: Map<address, i256> loans: Map<(address, address), i256> pub fn demo(self, ann: address, bob: address): let is_loan: bool = false self.give(from: ann, to: bob, 100, is_loan) fn transfer(self, from sender: address, to recipient: address, _ val: u256, is_loan: bool): self.cred[sender] -= val self.cred[recipient] += val if is_loan: self.loans[(sender, recipient)] += val
Note that arguments must be provided in the order specified in the function
definition.A parameter's label defaults to the parameter name, but can be changed by
specifying a different label to the left of the parameter name. Labels should be
clear and convenient for the caller, while parameter names are only used in the
function body, and can thus be longer and more descriptive.
In the example above, we choose to usesender
andrecipient
as identifiers
in the body offn transfer
, but use labelsfrom:
andto:
.In cases where it's ideal to not have labels, e.g. if a function takes a single
argument, or if types are sufficient to differentiate between arguments, use_
to specify that a given parameter has no label. It's also fine to require labels
for some arguments, but not others.Example:
fn add(_ x: u256, _ y: u256) -> u256: return x + y contract Foo: fn transfer(self, _ to: address, wei: u256): pass pub fn demo(self): transfer(address(0), wei: add(1000, 42))
(#397)
Bugfixes
- The region of memory used to compute the slot of a storage map value was not being allocated. (#684)
v0.14.0-alpha "Niter"
WARNING: All Fe releases are alpha releases and only meant to share the development progress with developers and enthusiasts. It is NOT yet ready for production usage.
0.14.0-alpha "Niter" (2022-03-02)
Features
-
Events can now be defined outside of contracts.
Example:
event Transfer: idx sender: address idx receiver: address value: u256 contract Foo: fn transferFoo(to: address, value: u256): emit Transfer(sender: msg.sender, receiver: to, value) contract Bar: fn transferBar(to: address, value: u256): emit Transfer(sender: msg.sender, receiver: to, value)
(#80)
-
The Fe standard library now includes a
std::evm
module, which provides functions that perform low-level evm operations.
Many of these are markedunsafe
, and thus can only be used inside of anunsafe
function or anunsafe
block.Example:
use std::evm::{mstore, mload} fn memory_shenanigans(): unsafe: mstore(0x20, 42) let x: u256 = mload(0x20) assert x == 42
The global functions
balance
andbalance_of
have been removed; these can now be called asstd::evm::balance()
, etc.
The global functionsend_value
has been ported to Fe, and is now available asstd::send_value
.
(#629) -
Support structs that have non-base type fields in storage.
Example:
struct Point: pub x: u256 pub y: u256 struct Bar: pub name: String<3> pub numbers: Array<u256, 2> pub point: Point pub something: (u256, bool) contract Foo: my_bar: Bar pub fn complex_struct_in_storage(self) -> String<3>: self.my_bar = Bar( name: "foo", numbers: [1, 2], point: Point(x: 100, y: 200), something: (1, true), ) # Asserting the values as they were set initially assert self.my_bar.numbers[0] == 1 assert self.my_bar.numbers[1] == 2 assert self.my_bar.point.x == 100 assert self.my_bar.point.y == 200 assert self.my_bar.something.item0 == 1 assert self.my_bar.something.item1 # We can change the values of the array self.my_bar.numbers[0] = 10 self.my_bar.numbers[1] = 20 assert self.my_bar.numbers[0] == 10 assert self.my_bar.numbers[1] == 20 # We can set the array itself self.my_bar.numbers = [1, 2] assert self.my_bar.numbers[0] == 1 assert self.my_bar.numbers[1] == 2 # We can change the values of the Point self.my_bar.point.x = 1000 self.my_bar.point.y = 2000 assert self.my_bar.point.x == 1000 assert self.my_bar.point.y == 2000 # We can set the point itself self.my_bar.point = Point(x=100, y=200) assert self.my_bar.point.x == 100 assert self.my_bar.point.y == 200 # We can change the value of the tuple self.my_bar.something.item0 = 10 self.my_bar.something.item1 = false assert self.my_bar.something.item0 == 10 assert not self.my_bar.something.item1 # We can set the tuple itself self.my_bar.something = (1, true) assert self.my_bar.something.item0 == 1 assert self.my_bar.something.item1 return self.my_bar.name.to_mem()
(#636)
-
Features that read and modify state outside of contracts are now implemented on a struct
named "Context".Context
is included in the standard library and can be imported with
use std::context::Context
. Instances ofContext
are created by calls to public functions
that declare it in the signature or by unsafe code.Basic example:
use std::context::Context contract Foo: my_num: u256 pub fn baz(ctx: Context) -> u256: return ctx.block_number() pub fn bing(self, new_num: u256) -> u256: self.my_num = new_num return self.my_num contract Bar: pub fn call_baz(ctx: Context, foo_addr: address) -> u256: # future syntax: `let foo = ctx.load<Foo>(foo_addr)` let foo: Foo = Foo(ctx, foo_addr) return foo.baz() pub fn call_bing(ctx: Context) -> u256: # future syntax: `let foo = ctx.create<Foo>(0)` let foo: Foo = Foo.create(ctx, 0) return foo.bing(42)
Example with
__call__
and unsafe block:use std::context::Context use std::evm contract Foo: pub fn __call__(): unsafe: # creating an instance of `Context` is unsafe let ctx: Context = Context() let value: u256 = u256(bar(ctx)) # return `value` evm::mstore(0, value) evm::return_mem(0, 32) fn bar(ctx: Context) -> address: return ctx.self_address()
(#638)
-
Features
Support local constant
Example:
contract Foo: pub fn bar(): const LOCAL_CONST: i32 = 1
Support constant expression
Example:
const GLOBAL: i32 = 8 contract Foo: pub fn bar(): const LOCAL: i32 = GLOBAL * 8
Support constant generics expression
Example:
const GLOBAL: u256= 8 const USE_GLOBAL: bool = false type MY_ARRAY = Array<i32, { GLOBAL / 4 }> contract Foo: pub fn bar(): let my_array: Array<i32, { GLOBAL if USE_GLOBAL else 4 }>
Bug fixes
Fix ICE when constant type is mismatch
Example:
const GLOBAL: i32 = "FOO" contract Foo: pub fn bar(): let FOO: i32 = GLOBAL
Fix ICE when assigning value to constant twice
Example:
const BAR: i32 = 1 contract FOO: pub fn bar(): BAR = 10
(#649)
-
Argument label syntax now uses
:
instead of=
. Example:struct Foo: x: u256 y: u256 let x: MyStruct = MyStruct(x: 10, y: 11) # previously: MyStruct(x = 10, y = 11)
(#665)
-
Support module-level
pub
modifier, now default visibility of items in a module is private.Example:
# This constant can be used outside of the module. pub const PUBLIC:i32 = 1 # This constant can NOT be used outside of the module. const PRIVATE: i32 = 1
(#677)
Internal Changes - for Fe Contributors
-
- Source files are now managed by a (salsa)
SourceDb
. ASourceFileId
now corresponds to a salsa-internedFile
with a path. File content is a salsa input function. This is mostly so that the future (LSP) language server can update file content when the user types or saves, which will trigger a re-analysis of anything that changed. - An ingot's set of modules and dependencies are also salsa inputs, so that when the user adds/removes a file or dependency, analysis is rerun.
- Standalone modules (eg a module compiled with
fe fee.fe
) now have a fake ingot parent. Each Ingot has an IngotMode (Lib, Main, StandaloneModule), which is used to disallowingot::whatever
paths in standalone modules, and to determine the correct root module file. parse_module
now always returns anast::Module
, and thus aModuleId
will always exist for a source file, even if it contains fatal parse errors. If the parsing fails, the body will end with aModuleStmt::ParseError
node. The parsing will stop at all but the simplest of syntax errors, but this at least allows partial analysis of source file with bad syntax.ModuleId::ast(db)
is now a query that parses the module's file on demand, rather than the AST being interned into salsa. This makes handling parse diagnostics cleaner, and removes the up-front parsing of every module at ingot creation time.
- Source files are now managed by a (salsa)
(#628)
v0.13.0-alpha "Mixite"
WARNING: All Fe releases are alpha releases and only meant to share the development progress with developers and enthusiasts. It is NOT yet ready for production usage.
0.13.0-alpha "Mixite" (2022-01-31)
Features
-
Support private fields on structs
Public fields now need to be declared with the
pub
modifier, otherwise they default to private fields.
If a struct contains private fields it can not be constructed directly except from within the
struct itself. The recommended way is to implement a methodnew(...)
as demonstrated in the
following example.struct House: pub price: u256 pub size: u256 vacant: bool pub fn new(price: u256, size: u256) -> House return House(price=price, size=size, vacant=true) contract Manager: house: House pub fn create_house(price: u256, size: u256): self.house = House::new(price, size) let can_access_price: u256 = self.house.price # can not access `self.house.vacant` because the field is private
(#214)
- Support non-base type fields in structs
Support is currently limited in two ways:- Structs with complex fields can not be returned from public functions
- Structs with complex fields can not be stored in storage (#343)
- Addresses can now be explicitly cast to u256. For example:
fn f(addr: address) -> u256: return u256(addr) ``` ([#621](https://github.com/ethereum/fe/issues/621))
- A special function named
__call__
can now be defined in contracts.
The body of this function will execute in place of the standard dispatcher when the contract is called.
example (with intrinsics):contract Foo: pub fn __call__(self): unsafe: if __calldataload(0) == 1: __revert(0, 0) else: __return(0, 0)
(#622)
Bugfixes
- Fixed a crash that happend when using a certain unprintable ASCII char (#551)
- The argument to
revert
wasn't being lowered by the compiler,
meaning that somerevert
calls would cause a compiler panic
in later stages. For example:const BAD_MOJO: u256 = 0xdeaddead struct Error: code: u256 fn fail(): revert Error(code = BAD_MOJO)
(#619)
v0.12.0-alpha "Lyonsite"
WARNING: All Fe releases are alpha releases and only meant to share the development progress with developers and enthusiasts. It is NOT yet ready for production usage.
0.12.0-alpha "Lyonsite" (2021-12-31)
Features
-
Added unsafe low-level "intrinsic" functions, that perform raw evm operations.
For example:fn foo(): unsafe: __mtore(0, 5000) assert __mload(0) == 5000
The functions available are exactly those defined in yul's "evm dialect":
https://docs.soliditylang.org/en/v0.8.11/yul.html#evm-dialect
but with a double-underscore prefix. Egselfdestruct
->__selfdestruct
.These are intended to be used for implementing basic standard library functionality,
and shouldn't typically be needed in normal contract code.Note: some intrinsic functions don't return a value (eg
__log0
); using these
functions in a context that assumes a return value of unit type (eglet x: () = __log0(a, b)
)
will currently result in a compiler panic in the yul compilation phase. (#603) -
Added an out of bounds check for accessing array items.
If an array index is retrieved at an index that is not within
the bounds of the array it now reverts withPanic(0x32)
. (#606)
Bugfixes
-
Ensure ternary expression short circuit.
Example:
contract Foo: pub fn bar(input: u256) -> u256: return 1 if input > 5 else revert_me() fn revert_me() -> u256: revert return 0
Previous to this change, the code above would always revert no matter
which branch of the ternary expressions it would resolve to. That is because
both sides were evaluated and then one side was discarded. With this change,
only the branch that doesn't get picked won't get evaluated at all.The same is true for the boolean operations
and
andor
. (#488)
Internal Changes - for Fe Contributors
-
Added a globally available dummy std lib.
This library contains a single
get_42
function, which can be called usingstd::get_42()
. Once
low-level intrinsics have been added to the language, we can deleteget_42
and start adding
useful code. (#601)
v0.11.0-alpha "Karlite"
WARNING: All Fe releases are alpha releases and only meant to share the development progress with developers and enthusiasts. It is NOT yet ready for production usage.
0.11.0-alpha "Karlite" (2021-12-02)
Features
-
Added support for multi-file inputs.
Implementation details:
Mostly copied Rust's crate system, but use the the term ingot instead of crate.
Below is an example of an ingot's file tree, as supported by the current implementation.
`-- basic_ingot `-- src |-- bar | `-- baz.fe |-- bing.fe |-- ding | |-- dang.fe | `-- dong.fe `-- main.fe
There are still a few features that will be worked on over the coming months:
- source files accompanying each directory module (e.g.
my_mod.fe
) - configuration files and the ability to create library ingots
- test directories
- module-level
pub
modifier (all items in a module are public) mod
statements (all fe files in the input tree are public modules)
These things will be implemented in order of importance over the next few months. (#562)
- source files accompanying each directory module (e.g.
-
The syntax for array types has changed to match other generic types.
For example,u8[4]
is now writtenArray<u8, 4>
. (#571) -
Functions can now be defined on struct types. Example:
struct Point: x: u64 y: u64 # Doesn't take `self`. Callable as `Point.origin()`. # Note that the syntax for this will soon be changed to `Point::origin()`. pub fn origin() -> Point: return Point(x=0, y=0) # Takes `self`. Callable on a value of type `Point`. pub fn translate(self, x: u64, y: u64): self.x += x self.y += y pub fn add(self, other: Point) -> Point: let x: u64 = self.x + other.x let y: u64 = self.y + other.y return Point(x, y) pub fn hash(self) -> u256: return keccak256(self.abi_encode()) pub fn do_pointy_things(): let p1: Point = Point.origin() p1.translate(5, 10) let p2: Point = Point(x=1, y=2) let p3: Point = p1.add(p2) assert p3.x == 6 and p3.y == 12 ``` ([#577](https://github.com/ethereum/fe/issues/577))
Bugfixes
-
Fixed a rare compiler crash.
Example:
let my_array: i256[1] = [-1 << 1]
Previous to this fix, the given example would lead to an ICE. (#550)
-
Contracts can now
create
an instance of a contract defined later in a file.
This issue was caused by a weakness in the way we generated yul. (#596)
Internal Changes - for Fe Contributors
-
File IDs are now attached to
Span
s. (#587) -
The fe analyzer now builds a dependency graph of source code "items" (functions, contracts, structs, etc).
This is used in the yulgen phase to determine which items are needed in the yul (intermediate representation)
output. Note that the yul output is still cluttered with utility functions that may or may not be needed by
a given contract. These utility functions are defined in the yulgen phase and aren't tracked in the dependency
graph, so it's not yet possible to filter out the unused functions. We plan to move the definition of many
of these utility functions into fe; when this happens they'll become part of the dependency graph and will only
be included in the yul output when needed.The dependency graph will also enable future analyzer warnings about unused code. (#596)
v0.10.0-alpha "Jade"
Features
-
Support for module level constants for base types
Example:
const TEN = 10 contract pub fn do_moon_math(self) -> u256: return 4711 * TEN
The values of base type constants are always inlined. (#192)
-
Encode revert errors for ABI decoding as
Error(0x103)
notPanic(0x99)
(#492) -
Replaced
import
statements withuse
statements.Example:
use foo::{bar::*, baz as baz26}
Note: this only adds support for parsing
use
statements. (#547) -
Functions can no be defined outside of contracts. Example:
fn add_bonus(x: u256) -> u256: return x + 10 contract PointTracker: points: Map<address, u256> pub fn add_points(self, user: address, val: u256): self.points[user] += add_bonus(val) ``` ([#566](https://github.com/ethereum/fe/issues/566))
-
Implemented a
send_value(to: address, value_in_wei: u256)
function.
The function is similar to thesendValue
function by OpenZeppelin with the differences being that:- It reverts with
Error(0x100)
instead ofError("Address: insufficient balance")
to
safe more gas. - It uses
selfbalance()
instead ofbalance(address())
to safe more gas - It reverts with
Error(0x101)
instead ofError("Address: unable to send value, recipient may have reverted")
also to safe more gas. (#567)
- It reverts with
-
Added support for
unsafe
functions andunsafe
blocks within functions.
Note that there's currently no functionality within Fe that requires the use
ofunsafe
, but we plan to add built-inunsafe
functions that perform raw
evm operations which will only callable within anunsafe
block or function. (#569) -
Added
balance()
andbalance_of(account: address)
methods. (#572) -
Added support for explicit casting between numeric types.
Example:let a: i8 = i8(-1) let a1: i16 = i16(a) let a2: u16 = u16(a1) assert a2 == u16(65535) let b: i8 = i8(-1) let b1: u8 = u8(b) let b2: u16 = u16(b1) assert b2 == u16(255)
Notice that Fe allows casting between any two numeric types but does not allow
to change both the sign and the size of the type in one step as that would leave
room for ambiguity as the example above demonstrates. (#576)
Bugfixes
- Adjust numeric values loaded from memory or storage
Previous to this fix numeric values that were loaded from either memory or storage
were not properly loaded on the stack which could result in numeric values not
treated as intended.
Example:In the example abovecontract Foo: pub fn bar() -> i8: let in_memory: i8[1] = [-3] return in_memory[0]
bar()
would not return-3
but253
instead. (#524) - Propagate reverts from external contract calls.
Before this fix the following code toshould_revert()
orshould_revert2()
would succeed even though it clearly should not.With this fix the revert errors are properly passed upwards the call hierachy. (#574)contract A: contract_b: B pub fn __init__(contract_b: address): self.contract_b = B(contract_b) pub fn should_revert(): self.contract_b.fail() pub fn should_revert2(): self.contract_b.fail_with_custom_error() struct SomeError: pass contract B: pub fn fail(): revert pub fn fail_with_custom_error(): revert SomeError()
- Fixed bug in left shift operation.
Example:
Let's consider the value1
as anu8
which is represented as
the following 256 bit item on the EVM stack00..|00000001|
.
A left shift of8
bits (val << 8
) turns that into00..01|00000000|
.
Previous to this fix this resulted in the compiler taking256
as the
value for theu8
when clearly256
is not even in the range ofu8
anymore. With this fix the left shift operations was fixed to properly
"clean up" the result of the shift so that00..01|00000000|
turns into
00..00|00000000|
. (#575) - Ensure negation is checked and reverts with over/underflow if needed.
Example:
The minimum value for ani8
is-128
but the maximum value of ani8
is127
which means that negating-128
should lead to an overflow since
128
does not fit into ani8
. Before this fix, negation operations where
not checked for over/underflow resulting in returning the oversized value. (#578)
Internal Changes - for Fe Contributors
- In the analysis stage, all name resolution (of variable names, function names,
type names, etc used in code) now happens via a singleresolve_name
pathway,
so we can catch more cases of name collisions and log more helpful error messages. (#555) - Added a new category of tests: differential contract testing.
Each of these tests is pased on a pair of contracts where one implementation
is written in Fe and the other one is written in Solidity. The implementations
should have the same public APIs and are assumed to always return identical
results given equal inputs. The inputs are randomly generated usingproptest
and hence are expected to discover unknown bugs. (#578)
v0.9.0-alpha "Iridium"
0.9.0-alpha "Iridium"
Features
-
The
self
variable is no longer implicitly defined in code blocks. It must now be declared
as the first parameter in a function signature.Example:
contract Foo: my_stored_num: u256 pub fn bar(self, my_num: u256): self.my_stored_num = my_num pub fn baz(self): self.bar(my_pure_func()) pub fn my_pure_func() -> u256: return 42 + 26
(#520)
- The analyzer now disallows defining a type, variable, or function whose
name conflicts with a built-in type, function, or object.
Example:error: type name conflicts with built-in type ┌─ compile_errors/shadow_builtin_type.fe:1:6 │ 1 │ type u256 = u8 │ ^^^^ `u256` is a built-in type
(#539)
Bugfixes
- Fixed cases where the analyzer would correctly reject code, but would panic instead of logging an error message. (#534)
- Non-fatal parser errors (eg missing parentheses when defining a function that takes no arguments:
fn foo:
)
are no longer ignored if the semantic analysis stage succeeds. (#535) - Fixed issue #531 by adding a
$
to the front of lowered tuple names. (#546)
Internal Changes - for Fe Contributors
- Implemented pretty printing of Fe AST. (#540)
v0.8.0-alpha "Haxonite"
0.8.0-alpha "Haxonite" (2021-08-31)
WARNING: All Fe releases are alpha releases and only meant to share the development progress with developers and enthusiasts. It is NOT yet ready for production usage.
Features
-
Support quotes, tabs and carriage returns in string literals and otherwise
restrict string literals to the printable subset of the ASCII table. (#329) -
The analyzer now uses a query-based system, which fixes some shortcomings of the previous implementation.
- Types can now refer to other types defined later in the file.
Example:
type Posts = Map<PostId, PostBody> type PostId = u256 type PostBody = String<140>
- Duplicate definition errors now show the location of the original definition.
- The analysis of each function, type definition, etc happens independently, so an error in one
doesn't stop the analysis pass. This means fe can report more user errors in a single run of the compiler. (#468)
- Types can now refer to other types defined later in the file.
-
Function definitions are now denoted with the keyword fn instead of def. (#496)
-
Variable declarations are now preceded by the
let
keyword. Example:let x: u8 = 1
. (#509) -
Implemented support for numeric unary invert operator (
~
) (#526)
Bugfixes
-
Calling
self.__init__()
now results in a nice error instead of a panic in the yul compilation stage. (#468) -
Fixed an issue where certain expressions were not being moved to the correct location. (#493)
-
Fixed an issue with a missing return statement not properly detected.
Previous to this fix, the following code compiles but it should not:
contract Foo: pub fn bar(val: u256) -> u256: if val > 1: return 5
With this change, the compiler rightfully detects that the code is missing
areturn
orrevert
statement after theif
statement since it is not
guaranteed that the path of execution always follows the arm of theif
statement. (#497) -
Fixed a bug in the analyzer which allowed tuple item accessor names with a leading 0,
resulting in an internal compiler error in a later pass. Example:my_tuple.item001
.
These are now rejected with an error message. (#510) -
Check call argument labels for function calls.
Previously the compiler would not check any labels that were used
when making function calls onself
or external contracts.This can be especially problematic if gives developers the impression
that they could apply function arguments in any order as long as they
are named which is not the case.contract Foo: pub fn baz(): self.bar(val2=1, doesnt_even_exist=2) pub fn bar(val1: u256, val2: u256): pass
Code as the one above is now rightfully rejected by the compiler. (#517)
Improved Documentation
-
Various improvements and bug fixes to both the content and layout of the specification. (#489)
-
Document all remaining statements and expressions in the spec.
Also added a CI check to ensure code examples in the documentation
are validated against the latest compiler. (#514)
Internal Changes - for Fe Contributors
- Separated Fe type traits between crates. (#485)
v0.7.0-alpha "Galaxite"
WARNING: All Fe releases are alpha releases and only meant to share the development progress with developers and enthusiasts. It is NOT yet ready for production usage.
0.7.0-alpha "Galaxite" (2021-07-27)
Features
-
Enable the optimizer by default. The optimizer can still be disabled
by supplying--optimize=false
as an argument. (#439) -
The following checks are now performed while decoding data:
- The size of the encoded data fits within the size range known at compile-time.
- Values are correctly padded.
- unsigned integers, addresses, and bools are checked to have correct left zero padding
- the size of signed integers are checked
- bytes and strings are checked to have correct right padding
- Data section offsets are consistent with the size of preceding values in the data section.
- The dynamic size of strings does not exceed their maximum size.
- The dynamic size of byte arrays (
u8[n]
) is equal to the size of the array. (#440)
-
Type aliases can now include tuples. Example:
type InternetPoints = (address, u256)
(#459)
-
Revert with custom errors
Example:
struct PlatformError: code: u256 pub def do_something(): revert PlatformError(code=4711)
Error encoding follows Solidity which is based on EIP-838. This means that custom errors returned from Fe are fully compatible with Solidity. (#464)
-
- The builtin value
msg.sig
now has typeu256
. - Removed the
bytes[n]
type. The typeu8[n]
can be used in its placed and will be encoded as a dynamically-sized, but checked, bytes component. (#472)
- The builtin value
-
Encode certain reverts as panics.
With this change, the following reverts are encoded as
Panic(uint256)
with
the following panic codes:0x01
: An assertion that failed and did not specify an error message0x11
: An arithmetic expression resulted in an over- or underflow0x12
: An arithmetic expression divided or modulo by zero
The panic codes are aligned with the panic codes that Solidity uses. (#476)
Bugfixes
-
Fixed a crash when trying to access an invalid attribute on a string.
Example:
contract Foo: pub def foo(): "".does_not_exist
The above now yields a proper user error. (#444)
-
Ensure
String<N>
type is capitalized in error messages (#445) -
Fixed ICE when using a static string that spans over multiple lines.
Previous to this fix, the following code would lead to a compiler crash:
contract Foo: pub def return_with_newline() -> String<16>: return "foo balu"
The above code now works as intended. (#448)
-
Fixed ICE when using a tuple declaration and specifying a non-tuple type.
Fixed a second ICE when using a tuple declaration where the number of
target items doesn't match the number of items in the declared type. (#469)
Internal Changes - for Fe Contributors
-
- Cleaned up ABI encoding internals.
- Improved yulc panic formatting. (#472)