| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904 |
- // SPDX-License-Identifier: Apache-2.0
- use crate::{build_solidity, build_solidity_with_options};
- use num_bigint::{BigInt, BigUint, RandBigInt, Sign};
- use parity_scale_codec::{Decode, Encode};
- use rand::seq::SliceRandom;
- use rand::Rng;
- use std::ops::Add;
- use std::ops::Div;
- use std::ops::Mul;
- use std::ops::Sub;
- #[test]
- fn celcius_and_fahrenheit() {
- #[derive(Debug, PartialEq, Eq, Encode, Decode)]
- struct Val(u32);
- // parse
- let mut runtime = build_solidity(
- "
- contract test {
- function celcius2fahrenheit(int32 celcius) pure public returns (int32) {
- int32 fahrenheit = celcius * 9 / 5 + 32;
- return fahrenheit;
- }
- function fahrenheit2celcius(uint32 fahrenheit) pure public returns (uint32) {
- return (fahrenheit - 32) * 5 / 9;
- }
- }",
- );
- runtime.function("celcius2fahrenheit", Val(10).encode());
- assert_eq!(runtime.output(), Val(50).encode());
- runtime.function("fahrenheit2celcius", Val(50).encode());
- assert_eq!(runtime.output(), Val(10).encode());
- }
- #[test]
- fn digits() {
- #[derive(Debug, PartialEq, Eq, Encode, Decode)]
- struct Val32(u32);
- #[derive(Debug, PartialEq, Eq, Encode, Decode)]
- struct Val64(u64);
- // parse
- let mut runtime = build_solidity(
- "
- contract test {
- function digitslen(uint64 val) pure public returns (uint32) {
- uint32 count = 0;
- while (val > 0) {
- count++;
- val /= 10;
- }
- if (count == 0) {
- count = 1;
- }
- return count;
- }
- function sumdigits(int64 val) pure public returns (uint32) {
- uint32 sum = 0;
- while (val > 0) {
- sum += uint32(val % 10);
- val= val / 10;
- }
- return sum;
- }
- }",
- );
- runtime.function("digitslen", Val64(1234567).encode());
- assert_eq!(runtime.output(), Val32(7).encode());
- runtime.function("sumdigits", Val64(123456789).encode());
- assert_eq!(runtime.output(), Val32(45).encode());
- }
- #[test]
- fn large_loops() {
- #[derive(Debug, PartialEq, Eq, Encode, Decode)]
- struct Val32(u32);
- #[derive(Debug, PartialEq, Eq, Encode, Decode)]
- struct Val64(u64);
- // parse
- let mut runtime = build_solidity(
- "
- contract test {
- function foo(uint val) pure public returns (uint) {
- for (uint i =0 ; i < 100; i++ ) {
- val += i + 10;
- }
- return val;
- }
- function baz(int val) pure public returns (int) {
- return val * 1000_000;
- }
- function bar() public {
- assert(foo(10) == 5960);
- assert(baz(7_000_123) == 7_000_123_000_000);
- assert(baz(7_000_123_456_678) == 7_000_123_456_678_000_000);
- }
- }",
- );
- runtime.function("bar", Vec::new());
- let mut args = Val64(7000).encode();
- args.resize(32, 0);
- runtime.function("baz", args);
- let mut rets = Val64(7000000000).encode();
- rets.resize(32, 0);
- assert_eq!(runtime.output(), rets);
- }
- #[test]
- fn expressions() {
- #[derive(Debug, PartialEq, Eq, Encode, Decode)]
- struct Val16(u16);
- #[derive(Debug, PartialEq, Eq, Encode, Decode)]
- struct Val8(u8);
- // parse
- let mut runtime = build_solidity("
- contract test {
- // this is 2^254
- int constant large_value = 14474011154664524427946373126085988481658748083205070504932198000989141204992;
- function add_100(uint16 a) pure public returns (uint16) {
- unchecked {
- a -= 200;
- a += 300;
- }
- return a;
- }
- function clear_digit(uint8 a) pure public returns (uint8) {
- a /= 10;
- a *= 10;
- return a;
- }
- function low_digit(uint8 a) pure public returns (uint8) {
- a %= 10;
- return a;
- }
- function test_comparisons() pure public {
- {
- // test comparisons work, if will work even if sign/unsigned is broken
- uint64 left = 102;
- uint64 right = 103;
- assert(left < right);
- assert(left <= right);
- assert(left != right);
- assert(right > left);
- assert(right >= left);
- assert(right == 103);
- assert(left >= 102);
- assert(right <= 103);
- assert(!(right <= 102));
- }
- {
- // check if unsigned compare works correctly (will fail if signed compare is done)
- uint16 left = 102;
- uint16 right = 0x8001;
- assert(left < right);
- assert(left <= right);
- assert(left != right);
- assert(right > left);
- assert(right >= left);
- assert(right == 0x8001);
- assert(left >= 102);
- assert(right <= 0x8001);
- assert(!(right <= 102));
- }
- {
- // check if signed compare works correctly (will fail if unsigned compare is done)
- int left = -102;
- int right = large_value;
- assert(left < right);
- assert(left <= right);
- assert(left != right);
- assert(right > left);
- assert(right >= left);
- assert(right == large_value);
- assert(left >= -102);
- assert(right <= large_value);
- assert(!(right <= -102));
- }
- }
- function increments() public {
- uint a = 1;
- assert(a-- == 1);
- assert(a == 0);
- assert(a++ == 0);
- assert(a == 1);
- assert(--a == 0);
- assert(a == 0);
- assert(++a == 1);
- assert(a == 1);
- }
- }",
- );
- runtime.function("add_100", Val16(0xffc0).encode());
- assert_eq!(runtime.output(), Val16(36).encode());
- runtime.function("clear_digit", Val8(25).encode());
- assert_eq!(runtime.output(), Val8(20).encode());
- runtime.function("low_digit", Val8(25).encode());
- assert_eq!(runtime.output(), Val8(5).encode());
- runtime.function("test_comparisons", Vec::new());
- runtime.function("increments", Vec::new());
- }
- #[test]
- #[should_panic]
- fn divisions_by_zero() {
- // parse
- let mut runtime = build_solidity(
- "
- contract test {
- function do_test() public returns (uint){
- uint256 val = 100;
- return (val / 0);
- }
- }",
- );
- runtime.function("do_test", Vec::new());
- }
- #[test]
- fn divisions() {
- // parse
- let mut runtime = build_solidity(
- "
- contract test {
- uint constant large = 101213131318098987934191741;
- function do_test() public returns (uint) {
- assert(large / 1 == large);
- assert(large / (large + 102) == 0);
- assert(large / large == 1);
- assert(large % 1 == 0);
- assert(large % (large + 102) == large);
- assert(large % large == 0);
- return 0;
- }
- }",
- );
- runtime.function("do_test", Vec::new());
- }
- #[test]
- fn divisions64() {
- // parse
- let mut runtime = build_solidity(
- "
- contract test {
- uint64 constant large = 101213131318098987;
- function do_test() public returns (uint) {
- assert(large / 1 == large);
- assert(large / (large + 102) == 0);
- assert(large / large == 1);
- assert(large % 1 == 0);
- assert(large % (large + 102) == large);
- assert(large % large == 0);
- return 0;
- }
- }",
- );
- runtime.function("do_test", Vec::new());
- }
- #[test]
- fn divisions128() {
- #[derive(Debug, PartialEq, Eq, Encode, Decode)]
- struct Args(i128, i128);
- #[derive(Debug, PartialEq, Eq, Encode, Decode)]
- struct Rets(i128);
- // parse
- let mut runtime = build_solidity(
- "
- contract test {
- uint128 constant large = 101213131318098987;
- uint128 constant small = 99;
- int128 constant signed_large = 101213131318098987;
- int128 constant neg_signed_large = -101213131318098987;
- int128 constant signed_small = 99;
- function do_test() public returns (uint) {
- assert(large / 1 == large);
- assert(large / (large + 102) == 0);
- assert(large / large == 1);
- assert(large % 1 == 0);
- assert(large % (large + 102) == large);
- assert(large % large == 0);
- assert(small / 10 == 9);
- assert(small % 10 == 9);
- assert(large / 100000 == 1012131313180);
- assert(large % 100000 == 98987);
- return 0;
- }
- function do_signed_test() public returns (uint) {
- assert(signed_large / 1 == signed_large);
- assert(signed_large / (signed_large + 102) == 0);
- assert(signed_large / signed_large == 1);
- assert(signed_large % 1 == 0);
- assert(signed_large % (signed_large + 102) == signed_large);
- assert(signed_large % signed_large == 0);
- assert(signed_small / 10 == 9);
- assert(signed_small % 10 == 9);
- assert(signed_large / 100000 == 1012131313180);
- assert(signed_large % 100000 == 98987);
- assert(neg_signed_large / -100000 == 1012131313180);
- assert(signed_large / -100000 == -1012131313180);
- assert(-signed_large / 100000 == -1012131313180);
- assert(signed_large % -100000 == 98987);
- assert(-signed_large % 100000 == -98987);
- assert(-signed_large % -100000 == -98987);
- return 0;
- }
- function do_div(int128 x, int128 y) public returns (int128) {
- return x / y;
- }
- function return_neg() public returns (int128) {
- return -100;
- }
- function return_pos() public returns (int128) {
- return 255;
- }
- }",
- );
- runtime.function("do_test", Vec::new());
- runtime.function("return_neg", Vec::new());
- if let Ok(Rets(r)) = Rets::decode(&mut &runtime.output()[..]) {
- assert_eq!(r, -100);
- } else {
- panic!();
- }
- runtime.function("return_pos", Vec::new());
- if let Ok(Rets(r)) = Rets::decode(&mut &runtime.output()[..]) {
- assert_eq!(r, 255);
- } else {
- panic!();
- }
- runtime.function("do_div", Args(-9900, -100).encode());
- if let Ok(Rets(r)) = Rets::decode(&mut &runtime.output()[..]) {
- assert_eq!(r, 99);
- } else {
- panic!();
- }
- runtime.function("do_div", Args(-101213131318098987, -100000).encode());
- if let Ok(Rets(r)) = Rets::decode(&mut &runtime.output()[..]) {
- assert_eq!(r, 1012131313180);
- } else {
- panic!();
- }
- runtime.function("do_signed_test", Vec::new());
- }
- #[test]
- fn divisions256() {
- // parse
- let mut runtime = build_solidity(
- "
- contract test {
- uint256 constant large = 101213131318098987;
- uint256 constant small = 99;
- function do_test() public returns (uint) {
- assert(large / 1 == large);
- assert(large / (large + 102) == 0);
- assert(large / large == 1);
- assert(large % 1 == 0);
- assert(large % (large + 102) == large);
- assert(large % large == 0);
- assert(small / 10 == 9);
- assert(small % 10 == 9);
- assert(large / 100000 == 1012131313180);
- assert(large % 100000 == 98987);
- return 0;
- }
- }",
- );
- runtime.function("do_test", Vec::new());
- }
- #[test]
- fn complement() {
- // parse
- let mut runtime = build_solidity(
- "
- contract test {
- function do_test() public {
- uint8 x1 = 0;
- assert(~x1 == 255);
- int32 x2 = 0x7fefabcd;
- assert(uint32(~x2) == 0x80105432);
- }
- function do_complement(uint256 foo) public returns (uint) {
- return ~foo;
- }
- }",
- );
- runtime.function("do_test", Vec::new());
- let mut args = Vec::new();
- args.resize(32, 0);
- runtime.function("do_complement", args);
- let ret = runtime.output();
- assert!(ret.len() == 32);
- assert!(ret.into_iter().filter(|x| *x == 255).count() == 32);
- }
- #[test]
- fn bitwise() {
- // parse
- let mut runtime = build_solidity(
- "
- contract test {
- function do_test() public {
- uint8 x1 = 0xf0;
- uint8 x2 = 0x0f;
- assert(x1 | x2 == 0xff);
- assert(x1 ^ x2 == 0xff);
- assert(x1 & x2 == 0x00);
- assert(x1 ^ 0 == x1);
- int32 x3 = 0x7fefabcd;
- assert(x3 & 0xffff == 0xabcd);
- }
- function do_or(uint256 a, uint256 b) public returns (uint) {
- return a | b;
- }
- function do_and(uint256 a, uint256 b) public returns (uint) {
- return a & b;
- }
- function do_xor(uint256 a, uint256 b) public returns (uint) {
- return a ^ b;
- }
- }",
- );
- runtime.function("do_test", Vec::new());
- let mut args = Vec::new();
- args.resize(32, 0);
- args.resize(64, 0xff);
- runtime.function("do_xor", args);
- let ret = &runtime.output();
- assert!(ret.len() == 32);
- assert!(ret.iter().filter(|x| **x == 255).count() == 32);
- let mut args = Vec::new();
- args.resize(32, 0);
- args.resize(64, 0xff);
- runtime.function("do_or", args);
- let ret = &runtime.output();
- assert!(ret.len() == 32);
- assert!(ret.iter().filter(|x| **x == 255).count() == 32);
- let mut args = Vec::new();
- args.resize(32, 0);
- args.resize(64, 0xff);
- runtime.function("do_and", args);
- let ret = &runtime.output();
- assert!(ret.len() == 32);
- assert!(ret.iter().filter(|x| **x == 0).count() == 32);
- }
- #[test]
- fn shift() {
- // parse
- let mut runtime = build_solidity(
- "
- contract test {
- function do_test() public {
- uint8 x1 = 0xf0;
- uint8 x2 = 0x0f;
- assert(x1 >> 4 == 0x0f);
- assert(x2 << 4 == 0xf0);
- int x3 = -16;
- assert(x3 >> 2 == -4);
- uint x5 = 0xdead_0000_0000_0000_0000;
- assert(x5 >> 64 == 0xdead);
- x5 = 0xdead;
- assert(x5 << 64 == 0xdead_0000_0000_0000_0000);
- }
- }",
- );
- runtime.function("do_test", Vec::new());
- }
- #[test]
- fn assign_bitwise() {
- // parse
- let mut runtime = build_solidity(
- "
- contract test {
- function do_test() public {
- uint8 x1 = 0xf0;
- uint8 x2 = 0x0f;
- x1 |= x2;
- assert(x1 == 0xff);
- x1 = 0xf0; x2 = 0x0f;
- x1 ^= x2;
- assert(x1 == 0xff);
- x1 = 0xf0; x2 = 0x0f;
- x1 &= x2;
- assert(x1 == 0x00);
- x1 = 0xf0; x2 = 0x0f;
- x1 ^= 0;
- assert(x1 == x1);
- int32 x3 = 0x7fefabcd;
- x3 &= 0xffff;
- assert(x3 == 0xabcd);
- }
- function do_or(uint256 a, uint256 b) public returns (uint) {
- a |= b;
- return a;
- }
- function do_and(uint256 a, uint256 b) public returns (uint) {
- a &= b;
- return a;
- }
- function do_xor(uint256 a, uint256 b) public returns (uint) {
- a ^= b;
- return a;
- }
- }",
- );
- runtime.function("do_test", Vec::new());
- let mut args = Vec::new();
- args.resize(32, 0);
- args.resize(64, 0xff);
- runtime.function("do_xor", args);
- let ret = &runtime.output();
- assert!(ret.len() == 32);
- assert!(ret.iter().filter(|x| **x == 255).count() == 32);
- let mut args = Vec::new();
- args.resize(32, 0);
- args.resize(64, 0xff);
- runtime.function("do_or", args);
- let ret = &runtime.output();
- assert!(ret.len() == 32);
- assert!(ret.iter().filter(|x| **x == 255).count() == 32);
- let mut args = Vec::new();
- args.resize(32, 0);
- args.resize(64, 0xff);
- runtime.function("do_and", args);
- let ret = &runtime.output();
- assert!(ret.len() == 32);
- assert!(ret.iter().filter(|x| **x == 0).count() == 32);
- }
- #[test]
- fn assign_shift() {
- // parse
- let mut runtime = build_solidity(
- "
- contract test {
- function do_test() public {
- uint8 x1 = 0xf0;
- uint8 x2 = 0x0f;
- x1 >>= 4;
- x2 <<= 4;
- assert(x1 == 0x0f);
- assert(x2 == 0xf0);
- int x3 = -16;
- x3 >>= 2;
- assert(x3 == -4);
- uint x5 = 0xdead_0000_0000_0000_0000;
- x5 >>= 64;
- assert(x5 == 0xdead);
- x5 = 0xdead;
- x5 <<= 64;
- assert(x5 == 0xdead_0000_0000_0000_0000);
- }
- }",
- );
- runtime.function("do_test", Vec::new());
- }
- #[test]
- fn ternary() {
- // parse
- let mut runtime = build_solidity(
- "
- contract test {
- function do_test() public {
- uint8 x1 = 0xf0;
- uint8 x2 = 0x0f;
- assert((false ? x1 : x2) == x2);
- assert((true ? x1 : x2) == x1);
- }
- }",
- );
- runtime.function("do_test", Vec::new());
- }
- #[test]
- fn short_circuit_or() {
- // parse
- let mut runtime = build_solidity(
- "
- contract test {
- uint32 counter;
- function increase_counter() private returns (bool) {
- counter += 1;
- return true;
- }
- function increase_counter2() private returns (bool) {
- counter++;
- return true;
- }
- function do_test() public {
- assert(counter == 0);
- // if left of or is true, right is not evaluated
- assert(true || increase_counter());
- assert(counter == 0);
- assert(false || increase_counter2());
- assert(counter == 1);
- false && increase_counter();
- assert(counter == 1);
- true && increase_counter();
- assert(counter == 2);
- }
- }",
- );
- runtime.function("do_test", Vec::new());
- }
- #[test]
- fn short_circuit_and() {
- // parse
- let mut runtime = build_solidity(
- "
- contract test {
- uint32 counter;
- function increase_counter() private returns (bool) {
- counter |= 1;
- return false;
- }
- function increase_counter2() private returns (bool) {
- ++counter;
- return false;
- }
- function do_test() public {
- assert(counter == 0);
- increase_counter2();
- increase_counter2();
- assert(counter == 2);
- increase_counter();
- assert(counter == 3);
- counter = 0;
- // if left hand side is false, right hand side is not evaluated
- assert(!(false && increase_counter()));
- assert(counter == 0);
- assert(!(true && increase_counter2()));
- assert(counter == 1);
- false && increase_counter2();
- assert(counter == 1);
- counter = 0;
- true && increase_counter();
- assert(counter == 1);
- }
- }",
- );
- runtime.function("do_test", Vec::new());
- }
- #[test]
- fn power() {
- #[derive(Debug, PartialEq, Eq, Encode, Decode)]
- struct Val(u64);
- // parse
- let mut runtime = build_solidity(
- "
- contract c {
- function power(uint64 base, uint64 exp) public returns (uint64) {
- return base ** exp;
- }
- function power_with_cast() public returns (uint64) {
- return uint64(2 ** 32);
- }
- }",
- );
- // 4**5 = 1024
- let args = Val(4)
- .encode()
- .into_iter()
- .chain(Val(5).encode().into_iter())
- .collect();
- runtime.function("power", args);
- assert_eq!(runtime.output(), Val(1024).encode());
- // n ** 1 = n
- let args = Val(2345)
- .encode()
- .into_iter()
- .chain(Val(1).encode().into_iter())
- .collect();
- runtime.function("power", args);
- assert_eq!(runtime.output(), Val(2345).encode());
- // n ** 0 = 0
- let args = Val(0xdead_beef)
- .encode()
- .into_iter()
- .chain(Val(0).encode().into_iter())
- .collect();
- runtime.function("power", args);
- assert_eq!(runtime.output(), Val(1).encode());
- // 0 ** n = 0
- let args = Val(0)
- .encode()
- .into_iter()
- .chain(Val(0xdead_beef).encode().into_iter())
- .collect();
- runtime.function("power", args);
- assert_eq!(runtime.output(), Val(0).encode());
- runtime.function("power_with_cast", Vec::new());
- assert_eq!(runtime.output(), Val(0x1_0000_0000).encode());
- }
- #[test]
- fn large_power() {
- #[derive(Debug, PartialEq, Eq, Encode, Decode)]
- struct Val(u128);
- // parse
- let mut runtime = build_solidity(
- "
- contract c {
- function power(uint128 base, uint128 exp) public returns (uint128) {
- return base ** exp;
- }
- }",
- );
- // 4**5 = 1024
- let args = Val(4)
- .encode()
- .into_iter()
- .chain(Val(5).encode().into_iter())
- .collect();
- runtime.function("power", args);
- assert_eq!(runtime.output(), Val(1024).encode());
- // n ** 1 = n
- let args = Val(2345)
- .encode()
- .into_iter()
- .chain(Val(1).encode().into_iter())
- .collect();
- runtime.function("power", args);
- assert_eq!(runtime.output(), Val(2345).encode());
- // n ** 0 = 0
- let args = Val(0xdeadbeef)
- .encode()
- .into_iter()
- .chain(Val(0).encode().into_iter())
- .collect();
- runtime.function("power", args);
- assert_eq!(runtime.output(), Val(1).encode());
- // 0 ** n = 0
- let args = Val(0)
- .encode()
- .into_iter()
- .chain(Val(0xdeadbeef).encode().into_iter())
- .collect();
- runtime.function("power", args);
- assert_eq!(runtime.output(), Val(0).encode());
- // 10 ** 36 = 1000000000000000000000000000000000000
- let args = Val(10)
- .encode()
- .into_iter()
- .chain(Val(36).encode().into_iter())
- .collect();
- runtime.function("power", args);
- assert_eq!(
- runtime.output(),
- Val(1000000000000000000000000000000000000).encode()
- );
- }
- #[test]
- fn test_power_overflow_boundaries() {
- for width in (8..=256).step_by(8) {
- let src = r#"
- contract test {
- function pow(uintN a, uintN b) public returns (uintN) {
- return a ** b;
- }
- }"#
- .replace("intN", &format!("int{width}"));
- let mut contract = build_solidity_with_options(&src, false, false);
- let base = BigUint::from(2_u32);
- let mut base_data = base.to_bytes_le();
- let exp = BigUint::from(width - 1);
- let mut exp_data = exp.to_bytes_le();
- let width_rounded = (width / 8usize).next_power_of_two();
- base_data.resize(width_rounded, 0);
- exp_data.resize(width_rounded, 0);
- contract.function(
- "pow",
- base_data
- .clone()
- .into_iter()
- .chain(exp_data.into_iter())
- .collect(),
- );
- let res = BigUint::from(2_usize).pow((width - 1).try_into().unwrap());
- let mut res_data = res.to_bytes_le();
- res_data.resize(width / 8, 0);
- assert_eq!(contract.output()[..width / 8], res_data);
- let exp = exp.add(1_usize);
- let mut exp_data = exp.to_bytes_le();
- exp_data.resize(width_rounded, 0);
- contract.function_expect_failure(
- "pow",
- base_data.into_iter().chain(exp_data.into_iter()).collect(),
- );
- }
- }
- #[test]
- fn multiply() {
- let mut rng = rand::thread_rng();
- let size = 32;
- let mut runtime = build_solidity(
- "
- contract c {
- function multiply(uint a, uint b) public returns (uint) {
- unchecked {
- return a * b;
- }
- }
- function multiply_with_cast() public returns (uint64) {
- return uint64(255 * 255);
- }
- }",
- );
- runtime.function("multiply_with_cast", Vec::new());
- assert_eq!(runtime.output(), 65025u64.encode());
- let mut rand = || -> (BigInt, Vec<u8>) {
- let length = rng.gen::<usize>() % size;
- let mut data = Vec::new();
- data.resize_with(length + 1, || rng.gen());
- data.resize(size, 0);
- (BigInt::from_bytes_le(Sign::Plus, &data), data)
- };
- for _ in 0..1000 {
- let (a, a_data) = rand();
- let (b, b_data) = rand();
- println!("in: a:{a_data:?} b:{b_data:?}");
- runtime.function(
- "multiply",
- a_data.into_iter().chain(b_data.into_iter()).collect(),
- );
- println!("out: res:{:?}", runtime.output());
- let res = BigInt::from_bytes_le(Sign::Plus, &runtime.output());
- println!("{res} = {a} * {b}");
- // the result is truncated to $size bytes. We do this here by converting to Vec<u8> and truncating
- // it. A truncating bigint multiply would be nicer.
- let (_, mut res) = (a * b).to_bytes_le();
- res.resize(size, 0);
- assert_eq!(res, runtime.output());
- }
- }
- #[test]
- fn test_mul_within_range_signed() {
- // We generate a random value that fits N bits. Then, we multiply that value by 1, -1 or 0.
- let mut rng = rand::thread_rng();
- for width in (8..=256).step_by(8) {
- let src = r#"
- contract test {
- function mul(intN a, intN b) public returns (intN) {
- return a * b;
- }
- }"#
- .replace("intN", &format!("int{width}"));
- let width_rounded = (width / 8_usize).next_power_of_two();
- let mut runtime = build_solidity(&src);
- let a = rng.gen_bigint((width - 1).try_into().unwrap()).sub(1_u32);
- let a_sign = a.sign();
- let mut a_data = a.to_signed_bytes_le();
- let side = vec![-1, 0, 1];
- let b = BigInt::from(*side.choose(&mut rng).unwrap());
- let b_sign = b.sign();
- let mut b_data = b.to_signed_bytes_le();
- a_data.resize(width_rounded, sign_extend(a_sign));
- b_data.resize(width_rounded, sign_extend(b_sign));
- runtime.function(
- "mul",
- a_data.into_iter().chain(b_data.into_iter()).collect(),
- );
- let value = a * b;
- let value_sign = value.sign();
- let mut value_data = value.to_signed_bytes_le();
- value_data.resize(width / 8, sign_extend(value_sign));
- assert_eq!(value_data, runtime.output()[..width / 8]);
- }
- }
- #[test]
- fn test_mul_within_range() {
- let mut rng = rand::thread_rng();
- for width in (8..=256).step_by(8) {
- let src = r#"
- contract test {
- function mul(uintN a, uintN b) public returns (uintN) {
- return a * b;
- }
- }"#
- .replace("intN", &format!("int{width}"));
- let width_rounded = (width / 8usize).next_power_of_two();
- let mut runtime = build_solidity(&src);
- // The range of values that can be held in unsigned N bits is [0, 2^N-1]. Here we generate a random number within this range and multiply it by 1
- let a = rng.gen_biguint((width).try_into().unwrap());
- let mut a_data = a.to_bytes_le();
- let b = BigUint::from(1_u32);
- let mut b_data = b.to_bytes_le();
- a_data.resize(width_rounded, 0);
- b_data.resize(width_rounded, 0);
- runtime.function(
- "mul",
- a_data.into_iter().chain(b_data.into_iter()).collect(),
- );
- let value = a * b;
- let mut value_data = value.to_bytes_le();
- value_data.resize(width / 8, 0);
- assert_eq!(value_data, runtime.output()[..width / 8]);
- }
- }
- #[test]
- fn test_overflow_boundaries() {
- for width in (8..=256).step_by(8) {
- let src = r#"
- contract test {
- function mul(intN a, intN b) public returns (intN) {
- return a * b;
- }
- }"#
- .replace("intN", &format!("int{width}"));
- let mut contract = build_solidity_with_options(&src, false, false);
- // The range of values that can be held in signed N bits is [-2^(N-1), 2^(N-1)-1]. We generate these boundaries:
- let upper_boundary = BigInt::from(2_u32).pow(width - 1).sub(1_u32);
- let mut up_data = upper_boundary.to_signed_bytes_le();
- let lower_boundary = BigInt::from(2_u32).pow(width - 1).mul(-1_i32);
- let mut low_data = lower_boundary.to_signed_bytes_le();
- let second_op = BigInt::from(1_u32);
- let mut sec_data = second_op.to_signed_bytes_le();
- let width_rounded = (width as usize / 8).next_power_of_two();
- up_data.resize(width_rounded, 0);
- low_data.resize(width_rounded, 255);
- sec_data.resize(width_rounded, 0);
- // Multiply the boundaries by 1.
- contract.function(
- "mul",
- up_data
- .clone()
- .into_iter()
- .chain(sec_data.clone().into_iter())
- .collect(),
- );
- let res = upper_boundary.clone().mul(1_u32);
- let mut res_data = res.to_signed_bytes_le();
- res_data.resize((width / 8) as usize, 0);
- assert_eq!(res_data, contract.output()[..(width / 8) as usize]);
- contract.function(
- "mul",
- low_data
- .clone()
- .into_iter()
- .chain(sec_data.clone().into_iter())
- .collect(),
- );
- let res = lower_boundary.clone().mul(1_u32);
- let mut res_data = res.to_signed_bytes_le();
- res_data.resize((width / 8) as usize, 0);
- assert_eq!(res_data, contract.output()[..(width / 8) as usize]);
- let upper_boundary_plus_one = BigInt::from(2_u32).pow(width - 1);
- // We subtract 2 instead of one to make the number even, so that no rounding occurs when we divide by 2 later on.
- let lower_boundary_minus_two = BigInt::from(2_u32).pow(width - 1).mul(-1_i32).sub(2_i32);
- let upper_second_op = upper_boundary_plus_one.div(2_u32);
- let mut upper_second_op_data = upper_second_op.to_signed_bytes_le();
- let lower_second_op = lower_boundary_minus_two.div(2_u32);
- let mut lower_second_op_data = lower_second_op.to_signed_bytes_le();
- let mut two_data = BigInt::from(2_u32).to_signed_bytes_le();
- upper_second_op_data.resize(width_rounded, 0);
- two_data.resize(width_rounded, 0);
- lower_second_op_data.resize(width_rounded, 255);
- // This will generate a value more than the upper boundary.
- contract.function_expect_failure(
- "mul",
- upper_second_op_data
- .clone()
- .into_iter()
- .chain(two_data.clone().into_iter())
- .collect(),
- );
- // Generate a value less than the lower boundary
- contract.function_expect_failure(
- "mul",
- lower_second_op_data
- .clone()
- .into_iter()
- .chain(two_data.clone().into_iter())
- .collect(),
- );
- // Upper boundary * Upper boundary
- contract.function_expect_failure(
- "mul",
- up_data
- .clone()
- .into_iter()
- .chain(up_data.clone().into_iter())
- .collect(),
- );
- // Lower boundary * Lower boundary
- contract.function_expect_failure(
- "mul",
- low_data
- .clone()
- .into_iter()
- .chain(low_data.clone().into_iter())
- .collect(),
- );
- // Lower boundary * Upper boundary
- contract.function_expect_failure(
- "mul",
- low_data
- .clone()
- .into_iter()
- .chain(up_data.clone().into_iter())
- .collect(),
- );
- }
- }
- #[test]
- fn test_overflow_detect_signed() {
- let mut rng = rand::thread_rng();
- for width in (8..=256).step_by(8) {
- let src = r#"
- contract test {
- function mul(intN a, intN b) public returns (intN) {
- return a * b;
- }
- }"#
- .replace("intN", &format!("int{width}"));
- let mut contract = build_solidity_with_options(&src, false, false);
- // The range of values that can be held in signed N bits is [-2^(N-1), 2^(N-1)-1] .Generate a value that will overflow this range:
- let limit = BigInt::from(2_u32).pow(width - 1).sub(1_u32);
- // Generate a random number within the the range [(2^N-1)/2, (2^N-1) -1]
- let first_operand_rand =
- rng.gen_bigint_range(&(limit.clone().div(2usize)).add(1usize), &limit);
- let first_op_sign = first_operand_rand.sign();
- let mut first_op_data = first_operand_rand.to_signed_bytes_le();
- let width_rounded = (width as usize / 8).next_power_of_two();
- first_op_data.resize(width_rounded, sign_extend(first_op_sign));
- // Calculate a number that when multiplied by first_operand_rand, the result will overflow N bits
- let second_operand_rand = rng.gen_bigint_range(&BigInt::from(2usize), &limit);
- let second_op_sign = second_operand_rand.sign();
- let mut second_op_data = second_operand_rand.to_signed_bytes_le();
- second_op_data.resize(width_rounded, sign_extend(second_op_sign));
- contract.function_expect_failure(
- "mul",
- first_op_data
- .into_iter()
- .chain(second_op_data.clone().into_iter())
- .collect(),
- );
- // The range of values that can be held in signed N bits is [-2^(N-1), 2^(N-1)-1] .
- let lower_limit = BigInt::from(2_u32).pow(width - 1).sub(1usize).mul(-1_i32);
- // Generate a random number within the the range [-(2^N-1), -(2^N-1)/2]
- let first_operand_rand =
- rng.gen_bigint_range(&lower_limit, &(lower_limit.clone().div(2usize)).add(1usize));
- let first_op_sign = first_operand_rand.sign();
- let mut first_op_data = first_operand_rand.to_signed_bytes_le();
- first_op_data.resize(width_rounded, sign_extend(first_op_sign));
- contract.function_expect_failure(
- "mul",
- first_op_data
- .into_iter()
- .chain(second_op_data.into_iter())
- .collect(),
- );
- }
- }
- #[test]
- fn test_overflow_detect_unsigned() {
- let mut rng = rand::thread_rng();
- for width in (8..=256).step_by(8) {
- let src = r#"
- contract test {
- function mul(uintN a, uintN b) public returns (uintN) {
- return a * b;
- }
- }"#
- .replace("intN", &format!("int{width}"));
- let mut contract = build_solidity_with_options(&src, false, false);
- // The range of values that can be held in signed N bits is [-2^(N-1), 2^(N-1)-1].
- let limit = BigUint::from(2_u32).pow(width).sub(1_u32);
- // Generate a random number within the the range [(2^N-1)/2, 2^N -1]
- let first_operand_rand =
- rng.gen_biguint_range(&(limit.clone().div(2usize)).add(1usize), &limit);
- let mut first_op_data = first_operand_rand.to_bytes_le();
- let width_rounded = (width as usize / 8).next_power_of_two();
- first_op_data.resize(width_rounded, 0);
- // Calculate a number that when multiplied by first_operand_rand, the result will overflow N bits
- let second_operand_rand = rng.gen_biguint_range(&BigUint::from(2usize), &limit);
- let mut second_op_data = second_operand_rand.to_bytes_le();
- second_op_data.resize(width_rounded, 0);
- contract.function_expect_failure(
- "mul",
- first_op_data
- .into_iter()
- .chain(second_op_data.into_iter())
- .collect(),
- );
- }
- }
- #[test]
- fn bytes_bitwise() {
- #[derive(Debug, PartialEq, Eq, Encode, Decode)]
- struct Bytes3([u8; 3]);
- #[derive(Debug, PartialEq, Eq, Encode, Decode)]
- struct Bytes5([u8; 5]);
- #[derive(Debug, PartialEq, Eq, Encode, Decode)]
- struct BytesArray([u8; 7], u32);
- // parse
- let mut runtime = build_solidity(
- "
- contract c {
- function or(bytes5 x) public returns (bytes5 y) {
- y = x | hex\"80808080\";
- }
- function and(bytes5 x) public returns (bytes5) {
- return x & hex\"FFFF\";
- }
- function xor(bytes5 x) public returns (bytes5) {
- x ^= 0xFF00000000;
- return x;
- }
- function shift_left(bytes3 a) public returns (bytes5 b) {
- b = bytes5(a) << 8;
- }
- function shift_right(bytes3 a) public returns (bytes5 b) {
- b = bytes5(a) >> 8;
- }
- function shift_left2(bytes3 a) public returns (bytes5 b) {
- b = bytes5(a);
- b <<= 8;
- }
- function shift_right2(bytes3 a) public returns (bytes5 b) {
- b = bytes5(a);
- b >>= 8;
- }
- function bytes_length() public {
- bytes4 b4;
- assert(b4.length == 4);
- }
- function complement(bytes3 a) public returns (bytes3) {
- return ~a;
- }
- function bytes_array(bytes7 foo, uint32 index) public returns (bytes1) {
- return foo[index];
- }
- }",
- );
- runtime.function("or", Bytes5([0x01, 0x01, 0x01, 0x01, 0x01]).encode());
- assert_eq!(
- runtime.output(),
- Bytes5([0x81, 0x81, 0x81, 0x81, 0x01]).encode()
- );
- runtime.function("and", Bytes5([0x01, 0x01, 0x01, 0x01, 0x01]).encode());
- assert_eq!(runtime.output(), Bytes5([0x01, 0x01, 0, 0, 0]).encode());
- runtime.function("xor", Bytes5([0x01, 0x01, 0x01, 0x01, 0x01]).encode());
- assert_eq!(
- runtime.output(),
- Bytes5([0xfe, 0x01, 0x01, 0x01, 0x01]).encode()
- );
- // shifty-shift
- runtime.function("shift_left", Bytes3([0xf3, 0x7d, 0x03]).encode());
- assert_eq!(
- runtime.output(),
- Bytes5([0x7d, 0x03, 0x00, 0x00, 0x00]).encode()
- );
- runtime.function("shift_right", Bytes3([0xf3, 0x7d, 0x03]).encode());
- assert_eq!(
- runtime.output(),
- Bytes5([0x00, 0xf3, 0x7d, 0x03, 0x00]).encode()
- );
- // assignment versions
- runtime.function("shift_left2", Bytes3([0xf3, 0x7d, 0x03]).encode());
- assert_eq!(
- runtime.output(),
- Bytes5([0x7d, 0x03, 0x00, 0x00, 0x00]).encode()
- );
- runtime.function("shift_right2", Bytes3([0xf3, 0x7d, 0x03]).encode());
- assert_eq!(
- runtime.output(),
- Bytes5([0x00, 0xf3, 0x7d, 0x03, 0x00]).encode()
- );
- // check length
- runtime.function("bytes_length", Vec::new());
- // complement
- runtime.function("complement", Bytes3([0xf3, 0x7d, 0x03]).encode());
- assert_eq!(runtime.output(), Bytes3([0x0c, 0x82, 0xfc]).encode());
- // array access
- let bytes7 = *b"NAWABRA";
- for i in 0..6 {
- runtime.function("bytes_array", BytesArray(bytes7, i).encode());
- assert_eq!(runtime.output(), [bytes7[i as usize]]);
- }
- }
- #[test]
- #[should_panic]
- fn bytesn_underflow_index_acccess() {
- #[derive(Debug, PartialEq, Eq, Encode, Decode)]
- struct BytesArray([u8; 7], i32);
- // parse
- let mut runtime = build_solidity(
- "
- contract test {
- function bytes_array(bytes7 foo, int32 index) public returns (bytes1) {
- return foo[index];
- }
- }",
- );
- runtime.function("bytes_array", BytesArray(*b"nawabra", -1).encode());
- }
- #[test]
- #[should_panic]
- fn bytesn_overflow_index_acccess() {
- #[derive(Debug, PartialEq, Eq, Encode, Decode)]
- struct BytesArray([u8; 7], i32);
- // parse
- let mut runtime = build_solidity(
- "
- contract test {
- function bytes_array(bytes7 foo, int32 index) public returns (byte) {
- return foo[index];
- }
- }",
- );
- runtime.function("bytes_array", BytesArray(*b"nawabra", 7).encode());
- }
- #[test]
- fn negation_and_subtract() {
- // The minus sign can be a unary negative or subtract.
- let mut runtime = build_solidity(
- r#"
- contract c {
- function test() public {
- uint32 x = 10-10;
- assert(x == 0);
- int32 y = -10-10;
- assert(y == -20);
- }
- }"#,
- );
- runtime.function("test", Vec::new());
- }
- #[test]
- fn div() {
- // The minus sign can be a unary negative or subtract.
- let mut runtime = build_solidity(
- r#"
- contract c {
- function test1() public {
- // see https://solidity.readthedocs.io/en/latest/types.html#modulo
- assert(int256(5) % int256(2) == int256(1));
- assert(int256(5) % int256(-2) == int256(1));
- assert(int256(-5) % int256(2) == int256(-1));
- assert(int256(-5) % int256(-2) == int256(-1));
- assert(int64(5) % int64(2) == int64(1));
- assert(int64(5) % int64(-2) == int64(1));
- assert(int64(-5) % int64(2) == int64(-1));
- assert(int64(-5) % int64(-2) == int64(-1));
- }
- function test2() public {
- // see https://github.com/hyperledger/burrow/pull/1367#issue-399914366
- assert(int256(7) / int256(3) == int256(2));
- assert(int256(7) / int256(-3) == int256(-2));
- assert(int256(-7) / int256(3) == int256(-2));
- assert(int256(-7) / int256(-3) == int256(2));
- assert(int256(7) % int256(3) == int256(1));
- assert(int256(7) % int256(-3) == int256(1));
- assert(int256(-7) % int256(3) == int256(-1));
- assert(int256(-7) % int256(-3) == int256(-1));
- assert(int64(7) / int64(3) == int64(2));
- assert(int64(7) / int64(-3) == int64(-2));
- assert(int64(-7) / int64(3) == int64(-2));
- assert(int64(-7) / int64(-3) == int64(2));
- assert(int64(7) % int64(3) == int64(1));
- assert(int64(7) % int64(-3) == int64(1));
- assert(int64(-7) % int64(3) == int64(-1));
- assert(int64(-7) % int64(-3) == int64(-1));
- }
- }"#,
- );
- runtime.function("test1", Vec::new());
- runtime.function("test2", Vec::new());
- }
- #[test]
- fn destructure() {
- // The minus sign can be a unary negative or subtract.
- let mut runtime = build_solidity(
- r#"
- contract c {
- function test() public {
- int a;
- int b;
- // test one
- (a, b) = (102, 3);
- assert(b == 3 && a == 102);
- // test missing one
- (a, , b) = (1, 2, 3);
- assert(a == 1 && b == 3);
- // test single one
- (a) = 5;
- assert(a == 5);
- // or like so
- (a) = (105);
- assert(a == 105);
- }
- function swap() public {
- int32 a;
- int32 b;
- // test one
- (a, b) = (102, 3);
- // test swap
- (b, a) = (a, b);
- assert(a == 3 && b == 102);
- }
- }"#,
- );
- runtime.function("test", Vec::new());
- runtime.function("swap", Vec::new());
- // The minus sign can be a unary negative or subtract.
- let mut runtime = build_solidity(
- r#"
- contract c {
- function test() public {
- // test one
- (int32 a, int32 b) = (102, 3);
- assert(b == 3 && a == 102);
- // test missing one
- (a, , b) = (1, 2, 3);
- assert(a == 1 && b == 3);
- // test single one
- (a) = 5;
- assert(a == 5);
- // or like so
- (a) = (105);
- assert(a == 105);
- }
- }"#,
- );
- runtime.function("test", Vec::new());
- }
- #[test]
- #[should_panic]
- fn addition_overflow() {
- let mut runtime = build_solidity_with_options(
- r#"
- contract overflow {
- function foo(uint8 x) internal returns (uint8) {
- uint8 y = x + 1;
- return y;
- }
- function bar() public {
- foo(255);
- }
- }
- "#,
- false,
- false,
- );
- runtime.function("bar", Vec::new());
- }
- #[test]
- fn unchecked_addition_overflow() {
- let mut runtime = build_solidity_with_options(
- r#"
- contract overflow {
- function foo(uint8 x) internal returns (uint8) {
- unchecked {
- uint8 y = x + 1;
- return y;
- }
- }
- function bar() public {
- foo(255);
- }
- }
- "#,
- false,
- false,
- );
- runtime.function("bar", Vec::new());
- }
- #[test]
- #[should_panic]
- fn subtraction_underflow() {
- let mut runtime = build_solidity_with_options(
- r#"
- contract underflow {
- function foo(uint64 x) internal returns (uint64) {
- uint64 y = x - 1;
- return y;
- }
- function bar() public {
- foo(0);
- }
- }
- "#,
- false,
- false,
- );
- runtime.function("bar", Vec::new());
- }
- #[test]
- fn unchecked_subtraction_underflow() {
- let mut runtime = build_solidity_with_options(
- r#"
- contract underflow {
- function foo(uint64 x) internal returns (uint64) {
- unchecked {
- uint64 y = x - 1;
- return y;
- }
- }
- function bar() public {
- foo(0);
- }
- }
- "#,
- false,
- false,
- );
- runtime.function("bar", Vec::new());
- }
- #[test]
- #[should_panic]
- fn multiplication_overflow() {
- let mut runtime = build_solidity_with_options(
- r#"
- contract overflow {
- function foo(int8 x) internal returns (int8) {
- int8 y = x * int8(64);
- return y;
- }
- function bar() public {
- foo(8);
- }
- }
- "#,
- false,
- false,
- );
- runtime.function("bar", Vec::new());
- }
- #[test]
- fn unchecked_multiplication_overflow() {
- let mut runtime = build_solidity_with_options(
- r#"
- contract overflow {
- function foo(int8 x) internal returns (int8) {
- unchecked {
- int8 y = x * int8(64);
- return y;
- }
- }
- function bar() public {
- foo(8);
- }
- }
- "#,
- false,
- false,
- );
- runtime.function("bar", Vec::new());
- }
- #[test]
- fn address_compare() {
- #[derive(Debug, PartialEq, Eq, Encode, Decode)]
- struct Args([u8; 32], [u8; 32]);
- let mut runtime = build_solidity(
- r#"
- contract addr {
- function bar() public {
- address left = address(1);
- address right = address(2);
- assert(left < right);
- assert(left <= right);
- assert(right > left);
- assert(right >= left);
- }
- function order(address tokenA, address tokenB) external returns (address token0, address token1) {
- require(tokenA != tokenB, 'UniswapV2: IDENTICAL_ADDRESSES');
- (token0, token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);
- }
- }"#,
- );
- runtime.function("bar", Vec::new());
- let address0: [u8; 32] = [
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 1,
- ];
- let address1: [u8; 32] = [
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 2,
- ];
- runtime.function("order", Args(address0, address1).encode());
- assert_eq!(runtime.output(), Args(address0, address1).encode());
- runtime.function("order", Args(address1, address0).encode());
- assert_eq!(runtime.output(), Args(address0, address1).encode());
- }
- #[test]
- fn address_pass_by_value() {
- let mut runtime = build_solidity(
- r#"
- contract addr {
- function bar() public {
- address left = address(1);
- foo(left);
- assert(left == address(1));
- }
- function foo(address a) internal {
- a = address(2);
- }
- }"#,
- );
- runtime.function("bar", Vec::new());
- }
- fn sign_extend(sign: Sign) -> u8 {
- if sign == Sign::Minus {
- 255
- } else {
- 0
- }
- }
|