From 2896d392c3c0588ac4565b96cfeb3e97423adfe7 Mon Sep 17 00:00:00 2001 From: Cyrill Leutwiler Date: Fri, 22 Sep 2023 17:25:01 +0200 Subject: [PATCH 1/5] wip Signed-off-by: Cyrill Leutwiler --- src/sema/ast.rs | 1 + src/sema/expression/member_access.rs | 69 +++++++++++-------- tests/contract_testcases/evm/address_code.sol | 10 +++ .../polkadot/builtins/address_code_01.sol | 10 +++ .../polkadot/builtins/address_code_02.sol | 8 +++ tests/evm.rs | 2 +- 6 files changed, 72 insertions(+), 28 deletions(-) create mode 100644 tests/contract_testcases/evm/address_code.sol create mode 100644 tests/contract_testcases/polkadot/builtins/address_code_01.sol create mode 100644 tests/contract_testcases/polkadot/builtins/address_code_02.sol diff --git a/src/sema/ast.rs b/src/sema/ast.rs index fe26c21f0..c528869d0 100644 --- a/src/sema/ast.rs +++ b/src/sema/ast.rs @@ -1586,6 +1586,7 @@ pub enum StringLocation { #[derive(PartialEq, Eq, Clone, Copy, Debug)] pub enum Builtin { + ContractCode, GetAddress, Balance, PayableSend, diff --git a/src/sema/expression/member_access.rs b/src/sema/expression/member_access.rs index a761aaa99..9f19049f7 100644 --- a/src/sema/expression/member_access.rs +++ b/src/sema/expression/member_access.rs @@ -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::Slice(Type::Uint(8).into())], + kind: Builtin::ContractCode, + args: vec![expr], + }); } Type::Contract(ref_contract_no) => { let mut name_matches = 0; diff --git a/tests/contract_testcases/evm/address_code.sol b/tests/contract_testcases/evm/address_code.sol new file mode 100644 index 000000000..9c96fb6b6 --- /dev/null +++ b/tests/contract_testcases/evm/address_code.sol @@ -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 uint8 slice to uint256 not possible diff --git a/tests/contract_testcases/polkadot/builtins/address_code_01.sol b/tests/contract_testcases/polkadot/builtins/address_code_01.sol new file mode 100644 index 000000000..e4cd841c6 --- /dev/null +++ b/tests/contract_testcases/polkadot/builtins/address_code_01.sol @@ -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 diff --git a/tests/contract_testcases/polkadot/builtins/address_code_02.sol b/tests/contract_testcases/polkadot/builtins/address_code_02.sol new file mode 100644 index 000000000..f55f720ad --- /dev/null +++ b/tests/contract_testcases/polkadot/builtins/address_code_02.sol @@ -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 diff --git a/tests/evm.rs b/tests/evm.rs index 6027ac301..00cc18093 100644 --- a/tests/evm.rs +++ b/tests/evm.rs @@ -249,7 +249,7 @@ fn ethereum_solidity_tests() { }) .sum(); - assert_eq!(errors, 1018); + assert_eq!(errors, 1016); } fn set_file_contents(source: &str, path: &Path) -> (FileResolver, Vec) { From 41657839df52d09924fe451548aa173d741990b8 Mon Sep 17 00:00:00 2001 From: Cyrill Leutwiler Date: Tue, 26 Sep 2023 13:27:45 +0200 Subject: [PATCH 2/5] Update src/sema/expression/member_access.rs Co-authored-by: Lucas Steuernagel <38472950+LucasSte@users.noreply.github.com> Signed-off-by: Cyrill Leutwiler --- src/sema/expression/member_access.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sema/expression/member_access.rs b/src/sema/expression/member_access.rs index 9f19049f7..779b3faf5 100644 --- a/src/sema/expression/member_access.rs +++ b/src/sema/expression/member_access.rs @@ -364,7 +364,7 @@ pub(super) fn member_access( if !is_this { diagnostics.push(Diagnostic::error( expr.loc(), - "polkadot can only retrieve balance of this, like 'address(this).balance'" + "polkadot can only retrieve balance of 'this', like 'address(this).balance'" .to_string(), )); return Err(()); From cd46cfbbc185a02924aeb5e4214ab4a156aa9efe Mon Sep 17 00:00:00 2001 From: Cyrill Leutwiler Date: Tue, 26 Sep 2023 13:38:04 +0200 Subject: [PATCH 3/5] code review suggestions Signed-off-by: Cyrill Leutwiler --- src/sema/expression/member_access.rs | 2 +- src/sema/mutability.rs | 3 ++- .../evm/{address_code.sol => address_code_01.sol} | 2 +- tests/contract_testcases/evm/address_code_02.sol | 10 ++++++++++ tests/contract_testcases/polkadot/value/balance.sol | 2 +- tests/contract_testcases/polkadot/value/balance_02.sol | 2 +- 6 files changed, 16 insertions(+), 5 deletions(-) rename tests/contract_testcases/evm/{address_code.sol => address_code_01.sol} (75%) create mode 100644 tests/contract_testcases/evm/address_code_02.sol diff --git a/src/sema/expression/member_access.rs b/src/sema/expression/member_access.rs index 779b3faf5..31f880a11 100644 --- a/src/sema/expression/member_access.rs +++ b/src/sema/expression/member_access.rs @@ -389,7 +389,7 @@ pub(super) fn member_access( used_variable(ns, &expr, symtable); return Ok(Expression::Builtin { loc: *loc, - tys: vec![Type::Slice(Type::Uint(8).into())], + tys: vec![Type::DynamicBytes], kind: Builtin::ContractCode, args: vec![expr], }); diff --git a/src/sema/mutability.rs b/src/sema/mutability.rs index 88138877e..37e2955c4 100644 --- a/src/sema/mutability.rs +++ b/src/sema/mutability.rs @@ -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), diff --git a/tests/contract_testcases/evm/address_code.sol b/tests/contract_testcases/evm/address_code_01.sol similarity index 75% rename from tests/contract_testcases/evm/address_code.sol rename to tests/contract_testcases/evm/address_code_01.sol index 9c96fb6b6..81808d5d0 100644 --- a/tests/contract_testcases/evm/address_code.sol +++ b/tests/contract_testcases/evm/address_code_01.sol @@ -7,4 +7,4 @@ contract UpgradeableProxy { } // ---- Expect: diagnostics ---- -// error: 5:9-38: conversion from uint8 slice to uint256 not possible +// error: 5:9-38: conversion from bytes to uint256 not possible diff --git a/tests/contract_testcases/evm/address_code_02.sol b/tests/contract_testcases/evm/address_code_02.sol new file mode 100644 index 000000000..c04ece516 --- /dev/null +++ b/tests/contract_testcases/evm/address_code_02.sol @@ -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 diff --git a/tests/contract_testcases/polkadot/value/balance.sol b/tests/contract_testcases/polkadot/value/balance.sol index 56384cdab..ce30b64e0 100644 --- a/tests/contract_testcases/polkadot/value/balance.sol +++ b/tests/contract_testcases/polkadot/value/balance.sol @@ -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' diff --git a/tests/contract_testcases/polkadot/value/balance_02.sol b/tests/contract_testcases/polkadot/value/balance_02.sol index 9955b2b0c..a23d67e74 100644 --- a/tests/contract_testcases/polkadot/value/balance_02.sol +++ b/tests/contract_testcases/polkadot/value/balance_02.sol @@ -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' From 971656c8f5d26701cbcf1da4eea53b13dea81b86 Mon Sep 17 00:00:00 2001 From: Cyrill Leutwiler Date: Tue, 26 Sep 2023 13:42:39 +0200 Subject: [PATCH 4/5] add non-failing EVM test Signed-off-by: Cyrill Leutwiler --- src/codegen/mod.rs | 2 ++ .../evm/{ => builtins}/address_code_01.sol | 0 .../evm/{ => builtins}/address_code_02.sol | 0 .../contract_testcases/evm/builtins/address_code_03.sol | 9 +++++++++ 4 files changed, 11 insertions(+) rename tests/contract_testcases/evm/{ => builtins}/address_code_01.sol (100%) rename tests/contract_testcases/evm/{ => builtins}/address_code_02.sol (100%) create mode 100644 tests/contract_testcases/evm/builtins/address_code_03.sol diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index 047f79002..e2b79205b 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -1738,6 +1738,7 @@ pub enum Builtin { BlockNumber, Calldata, ChainId, + ContractCode, Gasleft, GasLimit, Gasprice, @@ -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"), } } diff --git a/tests/contract_testcases/evm/address_code_01.sol b/tests/contract_testcases/evm/builtins/address_code_01.sol similarity index 100% rename from tests/contract_testcases/evm/address_code_01.sol rename to tests/contract_testcases/evm/builtins/address_code_01.sol diff --git a/tests/contract_testcases/evm/address_code_02.sol b/tests/contract_testcases/evm/builtins/address_code_02.sol similarity index 100% rename from tests/contract_testcases/evm/address_code_02.sol rename to tests/contract_testcases/evm/builtins/address_code_02.sol diff --git a/tests/contract_testcases/evm/builtins/address_code_03.sol b/tests/contract_testcases/evm/builtins/address_code_03.sol new file mode 100644 index 000000000..a0713de44 --- /dev/null +++ b/tests/contract_testcases/evm/builtins/address_code_03.sol @@ -0,0 +1,9 @@ +contract UpgradeableProxy { + function _setImplementation( + address newImplementation + ) public view returns (bytes memory) { + return newImplementation.code; + } +} + +// ---- Expect: diagnostics ---- From f97e7cf21015335bc4be5e4582fd12e9deb0e54b Mon Sep 17 00:00:00 2001 From: Cyrill Leutwiler Date: Tue, 26 Sep 2023 13:45:08 +0200 Subject: [PATCH 5/5] correct mutability fixes more EVM fails Signed-off-by: Cyrill Leutwiler --- tests/evm.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/evm.rs b/tests/evm.rs index e3238c41f..fa3aaf9b1 100644 --- a/tests/evm.rs +++ b/tests/evm.rs @@ -249,7 +249,7 @@ fn ethereum_solidity_tests() { }) .sum(); - assert_eq!(errors, 1010); + assert_eq!(errors, 1006); } fn set_file_contents(source: &str, path: &Path) -> (FileResolver, Vec) {