-
Notifications
You must be signed in to change notification settings - Fork 55
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
f4859dd
commit 955dc68
Showing
13 changed files
with
1,619 additions
and
1,265 deletions.
There are no files selected for viewing
1,265 changes: 0 additions & 1,265 deletions
1,265
crates/solc-expressions/src/func_call/intrinsic_call.rs
This file was deleted.
Oops, something went wrong.
128 changes: 128 additions & 0 deletions
128
crates/solc-expressions/src/func_call/intrinsic_call/abi.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
use crate::{ | ||
ContextBuilder, ExprErr, IntoExprErr, | ||
}; | ||
|
||
use graph::{ | ||
nodes::{ | ||
Builtin, ContextNode, ContextVar, ExprRet, | ||
}, | ||
AnalyzerBackend, ContextEdge, Edge, Node, | ||
}; | ||
|
||
use solang_parser::pt::{Expression, Loc}; | ||
|
||
impl<T> AbiCaller for T where T: AnalyzerBackend<Expr = Expression, ExprErr = ExprErr> + Sized {} | ||
pub trait AbiCaller: AnalyzerBackend<Expr = Expression, ExprErr = ExprErr> + Sized { | ||
fn abi_call(&mut self, func_name: String, input_exprs: &[Expression], loc: Loc, ctx: ContextNode) -> Result<(), ExprErr> { | ||
match &*func_name { | ||
"abi.decode" => { | ||
// we skip the first because that is what is being decoded. | ||
// TODO: check if we have a concrete bytes value | ||
fn match_decode( | ||
ctx: ContextNode, | ||
loc: &Loc, | ||
ret: ExprRet, | ||
analyzer: &mut impl AnalyzerBackend, | ||
) -> Result<(), ExprErr> { | ||
match ret { | ||
ExprRet::Single(expect_builtin) => { | ||
match analyzer.node(expect_builtin) { | ||
Node::Builtin(_) => { | ||
let var = ContextVar::new_from_builtin( | ||
*loc, | ||
expect_builtin.into(), | ||
analyzer, | ||
) | ||
.into_expr_err(*loc)?; | ||
let node = analyzer.add_node(Node::ContextVar(var)); | ||
ctx.add_var(node.into(), analyzer) | ||
.into_expr_err(*loc)?; | ||
analyzer.add_edge( | ||
node, | ||
ctx, | ||
Edge::Context(ContextEdge::Variable), | ||
); | ||
ctx.push_expr(ExprRet::Single(node), analyzer) | ||
.into_expr_err(*loc)?; | ||
Ok(()) | ||
} | ||
Node::ContextVar(cvar) => { | ||
let bn = analyzer | ||
.builtin_or_add( | ||
cvar.ty | ||
.as_builtin(analyzer) | ||
.into_expr_err(*loc)?, | ||
) | ||
.into(); | ||
let var = ContextVar::new_from_builtin( | ||
*loc, bn, analyzer, | ||
) | ||
.into_expr_err(*loc)?; | ||
let node = analyzer.add_node(Node::ContextVar(var)); | ||
ctx.add_var(node.into(), analyzer) | ||
.into_expr_err(*loc)?; | ||
analyzer.add_edge( | ||
node, | ||
ctx, | ||
Edge::Context(ContextEdge::Variable), | ||
); | ||
ctx.push_expr(ExprRet::Single(node), analyzer) | ||
.into_expr_err(*loc)?; | ||
Ok(()) | ||
} | ||
e => todo!("Unhandled type in abi.decode: {e:?}"), | ||
} | ||
} | ||
ExprRet::Multi(inner) => inner.iter().try_for_each(|i| { | ||
match_decode(ctx, loc, i.clone(), analyzer) | ||
}), | ||
ExprRet::CtxKilled(kind) => { | ||
ctx.kill(analyzer, *loc, kind).into_expr_err(*loc) | ||
} | ||
e => panic!("This is invalid solidity: {:?}", e), | ||
} | ||
} | ||
self.parse_ctx_expr(&input_exprs[1], ctx)?; | ||
self.apply_to_edges(ctx, loc, &|analyzer, ctx, loc| { | ||
let Some(ret) = | ||
ctx.pop_expr_latest(loc, analyzer).into_expr_err(loc)? | ||
else { | ||
return Err(ExprErr::NoRhs( | ||
loc, | ||
"abi.decode was not given the types for decoding" | ||
.to_string(), | ||
)); | ||
}; | ||
if matches!(ret, ExprRet::CtxKilled(_)) { | ||
ctx.push_expr(ret, analyzer).into_expr_err(loc)?; | ||
return Ok(()); | ||
} | ||
match_decode(ctx, &loc, ret, analyzer) | ||
}) | ||
} | ||
"abi.encode" | ||
| "abi.encodePacked" | ||
| "abi.encodeCall" | ||
| "abi.encodeWithSignature" | ||
| "abi.encodeWithSelector" => { | ||
// currently we dont support concrete abi encoding, TODO | ||
let bn = self.builtin_or_add(Builtin::DynamicBytes); | ||
let cvar = ContextVar::new_from_builtin(loc, bn.into(), self) | ||
.into_expr_err(loc)?; | ||
let node = self.add_node(Node::ContextVar(cvar)); | ||
ctx.add_var(node.into(), self).into_expr_err(loc)?; | ||
self.add_edge(node, ctx, Edge::Context(ContextEdge::Variable)); | ||
ctx.push_expr(ExprRet::Single(node), self) | ||
.into_expr_err(loc)?; | ||
Ok(()) | ||
} | ||
_ => Err(ExprErr::FunctionNotFound( | ||
loc, | ||
format!( | ||
"Could not find abi function: \"{func_name}\", context: {}", | ||
ctx.path(self), | ||
) | ||
)) | ||
} | ||
} | ||
} |
79 changes: 79 additions & 0 deletions
79
crates/solc-expressions/src/func_call/intrinsic_call/address.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
use crate::{ | ||
ExprErr, IntoExprErr, | ||
}; | ||
|
||
use graph::{ | ||
nodes::{ | ||
Builtin, ContextNode, ContextVar, ExprRet, | ||
}, | ||
AnalyzerBackend, ContextEdge, Edge, Node, | ||
}; | ||
|
||
use solang_parser::pt::{Expression, Loc}; | ||
|
||
impl<T> AddressCaller for T where T: AnalyzerBackend<Expr = Expression, ExprErr = ExprErr> + Sized {} | ||
pub trait AddressCaller: AnalyzerBackend<Expr = Expression, ExprErr = ExprErr> + Sized { | ||
fn address_call(&mut self, func_name: String, _input_exprs: &[Expression], loc: Loc, ctx: ContextNode) -> Result<(), ExprErr> { | ||
match &*func_name { | ||
"delegatecall" | "staticcall" | "call" => { | ||
// TODO: Check if we have the code for the address | ||
// if we dont, model it as a unrestricted call that can make other calls | ||
ctx.pop_expr_latest(loc, self).into_expr_err(loc)?; | ||
// TODO: try to be smarter based on the address input | ||
let booln = self.builtin_or_add(Builtin::Bool); | ||
let bool_cvar = ContextVar::new_from_builtin(loc, booln.into(), self) | ||
.into_expr_err(loc)?; | ||
let bool_node = self.add_node(Node::ContextVar(bool_cvar)); | ||
ctx.add_var(bool_node.into(), self).into_expr_err(loc)?; | ||
self.add_edge(bool_node, ctx, Edge::Context(ContextEdge::Variable)); | ||
|
||
let bn = self.builtin_or_add(Builtin::DynamicBytes); | ||
let cvar = ContextVar::new_from_builtin(loc, bn.into(), self) | ||
.into_expr_err(loc)?; | ||
let node = self.add_node(Node::ContextVar(cvar)); | ||
ctx.add_var(node.into(), self).into_expr_err(loc)?; | ||
self.add_edge(node, ctx, Edge::Context(ContextEdge::Variable)); | ||
ctx.push_expr( | ||
ExprRet::Multi(vec![ | ||
ExprRet::Single(bool_node), | ||
ExprRet::Single(node), | ||
]), | ||
self, | ||
) | ||
.into_expr_err(loc)?; | ||
Ok(()) | ||
} | ||
"code" => { | ||
// TODO: try to be smarter based on the address input | ||
let bn = self.builtin_or_add(Builtin::DynamicBytes); | ||
let cvar = ContextVar::new_from_builtin(loc, bn.into(), self) | ||
.into_expr_err(loc)?; | ||
let node = self.add_node(Node::ContextVar(cvar)); | ||
ctx.add_var(node.into(), self).into_expr_err(loc)?; | ||
self.add_edge(node, ctx, Edge::Context(ContextEdge::Variable)); | ||
ctx.push_expr(ExprRet::Single(node), self) | ||
.into_expr_err(loc)?; | ||
Ok(()) | ||
} | ||
"balance" => { | ||
// TODO: try to be smarter based on the address input | ||
let bn = self.builtin_or_add(Builtin::Uint(256)); | ||
let cvar = ContextVar::new_from_builtin(loc, bn.into(), self) | ||
.into_expr_err(loc)?; | ||
let node = self.add_node(Node::ContextVar(cvar)); | ||
ctx.add_var(node.into(), self).into_expr_err(loc)?; | ||
self.add_edge(node, ctx, Edge::Context(ContextEdge::Variable)); | ||
ctx.push_expr(ExprRet::Single(node), self) | ||
.into_expr_err(loc)?; | ||
Ok(()) | ||
} | ||
_ => Err(ExprErr::FunctionNotFound( | ||
loc, | ||
format!( | ||
"Could not find builtin address function: \"{func_name}\", context: {}", | ||
ctx.path(self), | ||
) | ||
)) | ||
} | ||
} | ||
} |
Oops, something went wrong.