Skip to content

Commit

Permalink
Support address.code in sema (hyperledger-solang#1549)
Browse files Browse the repository at this point in the history
  • Loading branch information
xermicus authored Sep 26, 2023
1 parent 4da8b2d commit d91fe95
Show file tree
Hide file tree
Showing 12 changed files with 97 additions and 31 deletions.
2 changes: 2 additions & 0 deletions src/codegen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1738,6 +1738,7 @@ pub enum Builtin {
BlockNumber,
Calldata,
ChainId,
ContractCode,
Gasleft,
GasLimit,
Gasprice,
Expand Down Expand Up @@ -1834,6 +1835,7 @@ impl From<&ast::Builtin> for Builtin {
ast::Builtin::ChainId => Builtin::ChainId,
ast::Builtin::BaseFee => Builtin::BaseFee,
ast::Builtin::PrevRandao => Builtin::PrevRandao,
ast::Builtin::ContractCode => Builtin::ContractCode,
_ => panic!("Builtin should not be in the cfg"),
}
}
Expand Down
1 change: 1 addition & 0 deletions src/sema/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1586,6 +1586,7 @@ pub enum StringLocation<T> {

#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub enum Builtin {
ContractCode,
GetAddress,
Balance,
PayableSend,
Expand Down
69 changes: 42 additions & 27 deletions src/sema/expression/member_access.rs
Original file line number Diff line number Diff line change
Expand Up @@ -347,37 +347,52 @@ pub(super) fn member_access(
}
_ => {}
},
Type::Address(_) => {
if id.name == "balance" {
if ns.target.is_polkadot() {
let mut is_this = false;

if let Expression::Cast { expr: this, .. } = &expr {
if let Expression::Builtin {
kind: Builtin::GetAddress,
..
} = this.as_ref()
{
is_this = true;
}
Type::Address(_) if id.name == "balance" => {
if ns.target.is_polkadot() {
let mut is_this = false;

if let Expression::Cast { expr: this, .. } = &expr {
if let Expression::Builtin {
kind: Builtin::GetAddress,
..
} = this.as_ref()
{
is_this = true;
}
}

if !is_this {
diagnostics.push(Diagnostic::error(
expr.loc(),
"polkadot can only retrieve balance of this, like 'address(this).balance'".to_string(),
));
return Err(());
}
if !is_this {
diagnostics.push(Diagnostic::error(
expr.loc(),
"polkadot can only retrieve balance of 'this', like 'address(this).balance'"
.to_string(),
));
return Err(());
}
used_variable(ns, &expr, symtable);
return Ok(Expression::Builtin {
loc: *loc,
tys: vec![Type::Value],
kind: Builtin::Balance,
args: vec![expr],
});
}
used_variable(ns, &expr, symtable);
return Ok(Expression::Builtin {
loc: *loc,
tys: vec![Type::Value],
kind: Builtin::Balance,
args: vec![expr],
});
}
Type::Address(_) if id.name == "code" => {
if ns.target != Target::EVM {
diagnostics.push(Diagnostic::error(
expr.loc(),
format!("'address.code' is not supported on {}", ns.target),
));
return Err(());
}
used_variable(ns, &expr, symtable);
return Ok(Expression::Builtin {
loc: *loc,
tys: vec![Type::DynamicBytes],
kind: Builtin::ContractCode,
args: vec![expr],
});
}
Type::Contract(ref_contract_no) => {
let mut name_matches = 0;
Expand Down
3 changes: 2 additions & 1 deletion src/sema/mutability.rs
Original file line number Diff line number Diff line change
Expand Up @@ -412,7 +412,8 @@ fn read_expression(expr: &Expression, state: &mut StateCheck) -> bool {
| Builtin::GasLimit
| Builtin::MinimumBalance
| Builtin::Balance
| Builtin::Accounts,
| Builtin::Accounts
| Builtin::ContractCode,
..
} => state.read(loc),

Expand Down
10 changes: 10 additions & 0 deletions tests/contract_testcases/evm/builtins/address_code_01.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
contract UpgradeableProxy {
function _setImplementation(
address newImplementation
) public pure returns (uint) {
return newImplementation.code;
}
}

// ---- Expect: diagnostics ----
// error: 5:9-38: conversion from bytes to uint256 not possible
10 changes: 10 additions & 0 deletions tests/contract_testcases/evm/builtins/address_code_02.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
contract UpgradeableProxy {
function _setImplementation(
address newImplementation
) public pure returns (bytes memory) {
return newImplementation.code;
}
}

// ---- Expect: diagnostics ----
// error: 5:16-38: function declared 'pure' but this expression reads from state
9 changes: 9 additions & 0 deletions tests/contract_testcases/evm/builtins/address_code_03.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
contract UpgradeableProxy {
function _setImplementation(
address newImplementation
) public view returns (bytes memory) {
return newImplementation.code;
}
}

// ---- Expect: diagnostics ----
10 changes: 10 additions & 0 deletions tests/contract_testcases/polkadot/builtins/address_code_01.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
contract UpgradeableProxy {
function _setImplementation(
address newImplementation
) public pure returns (bytes) {
return newImplementation.code;
}
}

// ---- Expect: diagnostics ----
// error: 5:16-33: 'address.code' is not supported on Polkadot
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
contract UpgradeableProxy {
function _setImplementation(address newImplementation) public view {
assert(newImplementation.code.length != 0);
}
}

// ---- Expect: diagnostics ----
// error: 3:16-33: 'address.code' is not supported on Polkadot
2 changes: 1 addition & 1 deletion tests/contract_testcases/polkadot/value/balance.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@
}
}
// ---- Expect: diagnostics ----
// error: 4:24-25: polkadot can only retrieve balance of this, like 'address(this).balance'
// error: 4:24-25: polkadot can only retrieve balance of 'this', like 'address(this).balance'
2 changes: 1 addition & 1 deletion tests/contract_testcases/polkadot/value/balance_02.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@
}
}
// ---- Expect: diagnostics ----
// error: 4:24-25: polkadot can only retrieve balance of this, like 'address(this).balance'
// error: 4:24-25: polkadot can only retrieve balance of 'this', like 'address(this).balance'
2 changes: 1 addition & 1 deletion tests/evm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ fn ethereum_solidity_tests() {
})
.sum();

assert_eq!(errors, 1012);
assert_eq!(errors, 1006);
}

fn set_file_contents(source: &str, path: &Path) -> (FileResolver, Vec<String>) {
Expand Down

0 comments on commit d91fe95

Please sign in to comment.