| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362 |
- // SPDX-License-Identifier: Apache-2.0
- use crate::build_solidity;
- use parity_scale_codec::{Decode, Encode};
- #[test]
- fn chain() {
- let mut runtime = build_solidity(
- r#"
- contract c {
- uint16 public var;
- modifier foo() {
- bool boom = true;
- if (boom) {
- _;
- }
- }
- function bar() foo() public {
- var = 7;
- }
- }"#,
- );
- runtime.constructor(0, Vec::new());
- let slot = [0u8; 32];
- assert_eq!(runtime.storage().get(&slot), None);
- runtime.function("bar", Vec::new());
- assert_eq!(runtime.storage().get(&slot).unwrap(), &vec!(7, 0));
- let mut runtime = build_solidity(
- r##"
- contract c {
- uint16 public var;
- modifier mod1 {
- var = 3;
- _;
- var = 5;
- }
- function test() mod1 public {
- assert(var == 3);
- var = 7;
- }
- }"##,
- );
- runtime.constructor(0, Vec::new());
- let slot = [0u8; 32];
- assert_eq!(runtime.storage().get(&slot), None);
- runtime.function("test", Vec::new());
- assert_eq!(runtime.storage().get(&slot).unwrap(), &vec!(5, 0));
- // now test modifier with argument and test that function argument is passed on
- let mut runtime = build_solidity(
- r##"
- contract c {
- uint16 public var;
- modifier mod1(uint16 v) {
- var = 3;
- _;
- assert(var == 11);
- var = v;
- }
- function test(uint16 x) mod1(x - 6) public {
- assert(var == 3);
- var = x;
- }
- }"##,
- );
- runtime.constructor(0, Vec::new());
- let slot = [0u8; 32];
- assert_eq!(runtime.storage().get(&slot), None);
- runtime.function("test", 11u16.encode());
- assert_eq!(runtime.storage().get(&slot).unwrap(), &vec!(5, 0));
- // now test modifier with argument and test that function argument is passed on
- let mut runtime = build_solidity(
- r##"
- contract c {
- uint16 public var;
- modifier mod1(uint16 v) {
- assert(var == 0);
- var = 3;
- _;
- assert(var == 17);
- var = v;
- }
- modifier mod2(uint16 v) {
- assert(var == 3);
- var = 9;
- _;
- assert(var == 11);
- var = v;
- }
- function test(uint16 x) mod1(x - 6) mod2(x + 6) public {
- assert(var == 9);
- var = x;
- }
- }"##,
- );
- runtime.constructor(0, Vec::new());
- let slot = [0u8; 32];
- assert_eq!(runtime.storage().get(&slot), None);
- runtime.function("test", 11u16.encode());
- assert_eq!(runtime.storage().get(&slot).unwrap(), &vec!(5, 0));
- // two placeholders means the following function is called twice.
- let mut runtime = build_solidity(
- r##"
- contract c {
- uint16 public var;
- modifier m {
- _;
- _;
- }
- function test() m public {
- var += 3;
- }
- }"##,
- );
- runtime.constructor(0, Vec::new());
- let slot = [0u8; 32];
- assert_eq!(runtime.storage().get(&slot), None);
- runtime.function("test", Vec::new());
- assert_eq!(runtime.storage().get(&slot).unwrap(), &vec!(6, 0));
- }
- #[test]
- fn inherit_modifier() {
- let mut runtime = build_solidity(
- r##"
- contract c is base {
- function test() md2 public {
- assert(s2 == 2);
- s2 += 3;
- }
- }
- abstract contract base {
- bool private s1;
- int32 internal s2;
- modifier md2 {
- s2 += 2;
- _;
- s2 += 2;
- }
- }"##,
- );
- runtime.constructor(0, Vec::new());
- let mut slot = [0u8; 32];
- slot[0] = 1;
- assert_eq!(runtime.storage().get(&slot), None);
- runtime.function("test", Vec::new());
- assert_eq!(runtime.storage().get(&slot).unwrap(), &vec!(7, 0, 0, 0));
- // now override it
- let mut runtime = build_solidity(
- r##"
- contract c is base {
- function test() md2 public {
- assert(s2 == 2);
- s2 += 3;
- }
- modifier md2 override {
- s2 += 2;
- _;
- s2 += 5;
- }
- }
- abstract contract base {
- bool private s1;
- int32 internal s2;
- modifier md2 virtual {
- s2 += 1;
- _;
- s2 += 1;
- }
- }"##,
- );
- runtime.constructor(0, Vec::new());
- let mut slot = [0u8; 32];
- slot[0] = 1;
- assert_eq!(runtime.storage().get(&slot), None);
- runtime.function("test", Vec::new());
- assert_eq!(runtime.storage().get(&slot).unwrap(), &vec!(10, 0, 0, 0));
- }
- #[test]
- fn return_values() {
- // in the modifier syntax, there are no return values
- // however, the generated cfg has the same arguments/returns the function is on attached
- // return simple value
- let mut runtime = build_solidity(
- r##"
- contract c {
- int64 s2;
- function test() md2 public returns (int64) {
- assert(s2 == 2);
- s2 += 3;
- return s2;
- }
- modifier md2 {
- s2 += 2;
- _;
- s2 += 2;
- }
- }"##,
- );
- runtime.constructor(0, Vec::new());
- runtime.function("test", Vec::new());
- #[derive(Debug, PartialEq, Eq, Encode, Decode)]
- struct Val(u64);
- assert_eq!(runtime.output(), Val(5).encode());
- let mut runtime = build_solidity(
- r##"
- struct S {
- int64 f1;
- string f2;
- }
- contract c {
- int64 s2;
- function test() md2 public returns (bool, S) {
- assert(s2 == 2);
- s2 += 3;
- return (true, S({ f1: s2, f2: "Hello, World!" }));
- }
- modifier md2 {
- s2 += 2;
- _;
- s2 += 2;
- }
- }"##,
- );
- runtime.constructor(0, Vec::new());
- runtime.function("test", Vec::new());
- #[derive(Debug, PartialEq, Eq, Encode, Decode)]
- struct StructS(bool, u64, String);
- assert_eq!(
- runtime.output(),
- StructS(true, 5, String::from("Hello, World!")).encode()
- );
- }
- #[test]
- fn repeated_modifier() {
- let mut runtime = build_solidity(
- r##"
- contract Test {
- modifier notZero(uint64 num) {
- require(num != 0, "invalid number");
- _;
- }
- function contfunc(uint64 num1, uint64 num2) public notZero(num1) notZero(num2) {
- // any code
- }
- }"##,
- );
- runtime.constructor(0, Vec::new());
- runtime.function_expect_failure("contfunc", (1u64, 0u64).encode());
- runtime.function_expect_failure("contfunc", (0u64, 0u64).encode());
- runtime.function_expect_failure("contfunc", (0u64, 1u64).encode());
- runtime.function("contfunc", (1u64, 1u64).encode());
- }
- #[test]
- fn modifier_in_library() {
- let mut runtime = build_solidity(
- r##"
- library LibWidthMod {
- modifier m(uint64 v) {
- require(v > 100);
- _;
- }
- function withMod(uint64 self) m(self) internal view {
- require(self > 10);
- }
- }
- contract Test {
- using LibWidthMod for uint64;
- function test(uint64 n) external {
- n.withMod();
- LibWidthMod.withMod(n);
- }
- }"##,
- );
- runtime.constructor(0, Vec::new());
- runtime.function_expect_failure("test", 0u64.encode());
- runtime.function_expect_failure("test", 50u64.encode());
- runtime.function_expect_failure("test", 100u64.encode());
- runtime.function("test", 200u64.encode());
- }
|