mirror of
https://github.com/pezkuwichain/revive.git
synced 2026-06-13 06:01:06 +00:00
switch to pallet_revive runtime (#40)
Signed-off-by: xermicus <cyrill@parity.io>
This commit is contained in:
@@ -14,11 +14,13 @@ alloy-sol-types = { workspace = true }
|
||||
hex = { workspace = true }
|
||||
env_logger = { workspace = true }
|
||||
log = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
|
||||
revive-solidity = { workspace = true }
|
||||
revive-differential = { workspace = true }
|
||||
revive-llvm-context = { workspace = true }
|
||||
revive-common = { workspace = true }
|
||||
revive-runner = { workspace = true }
|
||||
|
||||
[dev-dependencies]
|
||||
sha1 = { workspace = true }
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
{
|
||||
"Baseline": 934,
|
||||
"Computation": 4360,
|
||||
"DivisionArithmetics": 39824,
|
||||
"ERC20": 46471,
|
||||
"Events": 1749,
|
||||
"FibonacciIterative": 2973,
|
||||
"Flipper": 3563,
|
||||
"SHA1": 32543
|
||||
"Baseline": 878,
|
||||
"Computation": 4305,
|
||||
"DivisionArithmetics": 39774,
|
||||
"ERC20": 53405,
|
||||
"Events": 1693,
|
||||
"FibonacciIterative": 2917,
|
||||
"Flipper": 3570,
|
||||
"SHA1": 32557
|
||||
}
|
||||
@@ -1,5 +1,20 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/* runner.json
|
||||
|
||||
{
|
||||
"actions": [
|
||||
{
|
||||
"Instantiate": {
|
||||
"origin": "Alice",
|
||||
"value": 0
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
pragma solidity ^0.8;
|
||||
|
||||
contract Baseline {
|
||||
|
||||
@@ -2,6 +2,31 @@
|
||||
|
||||
pragma solidity ^0.8;
|
||||
|
||||
/* runner.json
|
||||
{
|
||||
"differential": true,
|
||||
"actions": [
|
||||
{
|
||||
"Instantiate": {
|
||||
"code": {
|
||||
"Solidity": {
|
||||
"contract": "Bitwise"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Call": {
|
||||
"dest": {
|
||||
"Instantiated": 0
|
||||
},
|
||||
"data": "3fa4f245"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
*/
|
||||
|
||||
contract Bitwise {
|
||||
function opByte(uint i, uint x) public payable returns (uint ret) {
|
||||
assembly {
|
||||
|
||||
@@ -2,12 +2,49 @@
|
||||
|
||||
pragma solidity ^0.8;
|
||||
|
||||
/* runner.json
|
||||
{
|
||||
"differential": true,
|
||||
"actions": [
|
||||
{
|
||||
"Instantiate": {
|
||||
"code": {
|
||||
"Solidity": {
|
||||
"contract": "Block"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Call": {
|
||||
"dest": {
|
||||
"Instantiated": 0
|
||||
},
|
||||
"data": "8381f58a"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Call": {
|
||||
"dest": {
|
||||
"Instantiated": 0
|
||||
},
|
||||
"data": "b80777ea"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
*/
|
||||
|
||||
contract Block {
|
||||
function timestamp() public view returns (uint ret) {
|
||||
ret = block.timestamp;
|
||||
}
|
||||
|
||||
function number() public view returns (uint ret) {
|
||||
ret = block.number;
|
||||
if (block.number == 0) {
|
||||
ret = 1;
|
||||
} else {
|
||||
ret = block.number;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,44 @@
|
||||
|
||||
pragma solidity ^0.8;
|
||||
|
||||
/* runner.json
|
||||
{
|
||||
"actions": [
|
||||
{
|
||||
"Instantiate": {}
|
||||
},
|
||||
{
|
||||
"Call": {
|
||||
"dest": {
|
||||
"Instantiated": 0
|
||||
},
|
||||
"data": "0f760610000000000000000000000000000000000000000000000000000000000000000d"
|
||||
}
|
||||
},
|
||||
{
|
||||
"VerifyCall": {
|
||||
"success": true,
|
||||
"output": "000000000000000000000000000000000000000000000000000000000000005b"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Call": {
|
||||
"dest": {
|
||||
"Instantiated": 0
|
||||
},
|
||||
"data": "00261b660000000000000000000000000000000000000000000000000000000000000005"
|
||||
}
|
||||
},
|
||||
{
|
||||
"VerifyCall": {
|
||||
"success": true,
|
||||
"output": "00000000000000000000000000000000000000000000000000000000000003b1"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
*/
|
||||
|
||||
contract Computation {
|
||||
function triangle_number(int64 n) public pure returns (int64 sum) {
|
||||
unchecked {
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity ^0.8.24;
|
||||
|
||||
/* runner.json
|
||||
{
|
||||
"actions": [
|
||||
{
|
||||
"Instantiate": {}
|
||||
},
|
||||
{
|
||||
"Call": {
|
||||
"dest": {
|
||||
"Instantiated": 0
|
||||
},
|
||||
"data": "f9fbd5540000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000c68656c6c6f20776f726c64210000000000000000000000000000000000000000"
|
||||
}
|
||||
},
|
||||
{
|
||||
"VerifyCall": {
|
||||
"success": true,
|
||||
"output": "57caa176af1ac0433c5df30e8dabcd2ec1af1e92a26eced5f719b88458777cd6"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
*/
|
||||
|
||||
contract TestSha3 {
|
||||
function test(string memory _pre) external payable returns (bytes32 hash) {
|
||||
hash = keccak256(bytes(_pre));
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,16 @@
|
||||
|
||||
pragma solidity ^0.8;
|
||||
|
||||
/* runner.json
|
||||
{
|
||||
"actions": [
|
||||
{
|
||||
"Instantiate": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
*/
|
||||
|
||||
// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.0.0/contracts/token/ERC20/IERC20.sol
|
||||
interface IERC20 {
|
||||
function totalSupply() external view returns (uint);
|
||||
|
||||
@@ -2,6 +2,43 @@
|
||||
|
||||
pragma solidity ^0.8;
|
||||
|
||||
/* runner.json
|
||||
{
|
||||
"differential": true,
|
||||
"actions": [
|
||||
{
|
||||
"Instantiate": {
|
||||
"code": {
|
||||
"Solidity": {
|
||||
"contract": "Events"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Call": {
|
||||
"dest": {
|
||||
"Instantiated": 0
|
||||
},
|
||||
"data": "4d43bec90000000000000000000000000000000000000000000000000000000000000000"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
*/
|
||||
|
||||
/* TODO when pallet_revive accepts Solidity event topics
|
||||
{
|
||||
"Call": {
|
||||
"dest": {
|
||||
"Instantiated": 0
|
||||
},
|
||||
"data": "4d43bec9000000000000000000000000000000000000000000000000000000000000007b"
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
contract Events {
|
||||
event A() anonymous;
|
||||
event E(uint, uint indexed, uint indexed, uint indexed);
|
||||
|
||||
@@ -2,7 +2,29 @@
|
||||
|
||||
pragma solidity ^0.8;
|
||||
|
||||
// https://medium.com/coinmonks/fibonacci-in-solidity-8477d907e22a
|
||||
/* runner.json
|
||||
{
|
||||
"actions": [
|
||||
{
|
||||
"Instantiate": {}
|
||||
},
|
||||
{
|
||||
"Call": {
|
||||
"dest": {
|
||||
"Instantiated": 0
|
||||
},
|
||||
"data": "6b83dd2e0000000000000000000000000000000000000000000000000000000000000006"
|
||||
}
|
||||
},
|
||||
{
|
||||
"VerifyCall": {
|
||||
"success": true,
|
||||
"output": "0000000000000000000000000000000000000000000000000000000000000008"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
*/
|
||||
|
||||
contract FibonacciRecursive {
|
||||
function f(uint n) internal pure returns (uint) {
|
||||
@@ -36,6 +58,7 @@ contract FibonacciIterative {
|
||||
}
|
||||
}
|
||||
|
||||
// https://medium.com/coinmonks/fibonacci-in-solidity-8477d907e22a
|
||||
contract FibonacciBinet {
|
||||
function fib3(uint n) external pure returns (uint a) {
|
||||
if (n == 0) {
|
||||
|
||||
@@ -2,6 +2,31 @@
|
||||
|
||||
pragma solidity ^0.8;
|
||||
|
||||
/* runner.json
|
||||
{
|
||||
"differential": true,
|
||||
"actions": [
|
||||
{
|
||||
"Instantiate": {
|
||||
"code": {
|
||||
"Solidity": {
|
||||
"contract": "MCopy"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Call": {
|
||||
"dest": {
|
||||
"Instantiated": 0
|
||||
},
|
||||
"data": "0ee188b0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000030102030000000000000000000000000000000000000000000000000000000000"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
*/
|
||||
|
||||
contract MCopy {
|
||||
function memcpy(bytes memory payload) public pure returns (bytes memory) {
|
||||
return payload;
|
||||
|
||||
@@ -2,6 +2,51 @@
|
||||
|
||||
pragma solidity ^0.8;
|
||||
|
||||
/* runner.json
|
||||
{
|
||||
"actions": [
|
||||
{
|
||||
"Instantiate": {
|
||||
"code": {
|
||||
"Solidity": {
|
||||
"contract": "MSize",
|
||||
"solc_optimizer": false
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Call": {
|
||||
"dest": {
|
||||
"Instantiated": 0
|
||||
},
|
||||
"data": "f016832c"
|
||||
}
|
||||
},
|
||||
{
|
||||
"VerifyCall": {
|
||||
"success": true,
|
||||
"output": "0000000000000000000000000000000000000000000000000000000000000060"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Call": {
|
||||
"dest": {
|
||||
"Instantiated": 0
|
||||
},
|
||||
"data": "f4a63aa5"
|
||||
}
|
||||
},
|
||||
{
|
||||
"VerifyCall": {
|
||||
"success": true,
|
||||
"output": "0000000000000000000000000000000000000000000000000000000000000084"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
*/
|
||||
|
||||
contract MSize {
|
||||
uint[] public data;
|
||||
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity ^0.8;
|
||||
|
||||
/* runner.json
|
||||
{
|
||||
"differential": true,
|
||||
"actions": [
|
||||
{
|
||||
"Instantiate": {
|
||||
"code": {
|
||||
"Solidity": {
|
||||
"contract": "MStore8"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Call": {
|
||||
"dest": {
|
||||
"Instantiated": 0
|
||||
},
|
||||
"data": "b09ad4210000000000000000000000000000000000000000000000000000000000000000"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Call": {
|
||||
"dest": {
|
||||
"Instantiated": 0
|
||||
},
|
||||
"data": "b09ad4210000000000000000000000000000000000000000000000000000000000000001"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Call": {
|
||||
"dest": {
|
||||
"Instantiated": 0
|
||||
},
|
||||
"data": "b09ad4210000000000000000000000000000000000000000000000000000000000000002"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Call": {
|
||||
"dest": {
|
||||
"Instantiated": 0
|
||||
},
|
||||
"data": "b09ad42100000000000000000000000000000000000000000000000000000000000000ff"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Call": {
|
||||
"dest": {
|
||||
"Instantiated": 0
|
||||
},
|
||||
"data": "b09ad4210000000000000000000000000000000000000000000000000000000000000100"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Call": {
|
||||
"dest": {
|
||||
"Instantiated": 0
|
||||
},
|
||||
"data": "b09ad4210000000000000000000000000000000000000000000000000000000000000101"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Call": {
|
||||
"dest": {
|
||||
"Instantiated": 0
|
||||
},
|
||||
"data": "b09ad4210000000000000000000000000000000000000000000000000000000000000102"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Call": {
|
||||
"dest": {
|
||||
"Instantiated": 0
|
||||
},
|
||||
"data": "b09ad42100000000000000000000000000000000000000000000000000000000075bcd15"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Call": {
|
||||
"dest": {
|
||||
"Instantiated": 0
|
||||
},
|
||||
"data": "b09ad421ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
*/
|
||||
|
||||
contract MStore8 {
|
||||
function mStore8(uint value) public pure returns (uint256 word) {
|
||||
assembly {
|
||||
mstore8(0x80, value)
|
||||
word := mload(0x80)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,31 @@
|
||||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
pragma solidity ^0.8.4;
|
||||
|
||||
/* runner.json
|
||||
{
|
||||
"differential": true,
|
||||
"actions": [
|
||||
{
|
||||
"Instantiate": {
|
||||
"code": {
|
||||
"Solidity": {
|
||||
"contract": "SHA1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Call": {
|
||||
"dest": {
|
||||
"Instantiated": 0
|
||||
},
|
||||
"data": "1605782b00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000200ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
*/
|
||||
|
||||
contract SHA1 {
|
||||
function sha1(bytes memory data) public pure returns (bytes20 ret) {
|
||||
assembly {
|
||||
|
||||
@@ -2,6 +2,31 @@
|
||||
|
||||
pragma solidity ^0.8;
|
||||
|
||||
/* runner.json
|
||||
{
|
||||
"differential": true,
|
||||
"actions": [
|
||||
{
|
||||
"Instantiate": {
|
||||
"code": {
|
||||
"Solidity": {
|
||||
"contract": "Storage"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Call": {
|
||||
"dest": {
|
||||
"Instantiated": 0
|
||||
},
|
||||
"data": "fabc9efaffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
*/
|
||||
|
||||
contract Storage {
|
||||
function transient(uint value) public returns (uint ret) {
|
||||
assembly {
|
||||
|
||||
@@ -1,7 +1,31 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity ^0.8;
|
||||
|
||||
/* runner.json
|
||||
{
|
||||
"differential": true,
|
||||
"actions": [
|
||||
{
|
||||
"Instantiate": {
|
||||
"code": {
|
||||
"Solidity": {
|
||||
"contract": "Value"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Call": {
|
||||
"dest": {
|
||||
"Instantiated": 0
|
||||
},
|
||||
"data": "3fa4f245"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
*/
|
||||
|
||||
contract Value {
|
||||
function value() public payable returns (uint ret) {
|
||||
ret = msg.value;
|
||||
|
||||
@@ -1,6 +1,44 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8;
|
||||
|
||||
/* runner.json
|
||||
{
|
||||
"actions": [
|
||||
{
|
||||
"Instantiate": {
|
||||
"data": "0000000000000000000000000000000000000000000000000000000000000001"
|
||||
}
|
||||
},
|
||||
{
|
||||
"VerifyStorage": {
|
||||
"contract": {
|
||||
"Instantiated": 0
|
||||
},
|
||||
"key": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"expected": "0100000000000000000000000000000000000000000000000000000000000000"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Call": {
|
||||
"dest": {
|
||||
"Instantiated": 0
|
||||
},
|
||||
"data": "cde4efa9"
|
||||
}
|
||||
},
|
||||
{
|
||||
"VerifyStorage": {
|
||||
"contract": {
|
||||
"Instantiated": 0
|
||||
},
|
||||
"key": "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"expected": "0000000000000000000000000000000000000000000000000000000000000000"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
*/
|
||||
|
||||
contract Flipper {
|
||||
bool coin;
|
||||
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity ^0.8;
|
||||
|
||||
contract MStore8 {
|
||||
function mStore8(uint value) public pure returns (uint256 word) {
|
||||
assembly {
|
||||
mstore8(0x80, value)
|
||||
word := mload(0x80)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,8 @@
|
||||
use alloy_primitives::{Address, I256, U256};
|
||||
use alloy_primitives::{Address, Bytes, I256, U256};
|
||||
use alloy_sol_types::{sol, SolCall, SolConstructor};
|
||||
|
||||
use revive_solidity::test_utils::*;
|
||||
|
||||
use crate::mock_runtime::{CallOutput, State};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Contract {
|
||||
pub name: &'static str,
|
||||
@@ -93,7 +91,7 @@ sol!(
|
||||
function sha1(bytes memory data) public pure returns (bytes20 ret);
|
||||
}
|
||||
);
|
||||
case!("SHA1.sol", SHA1, sha1Call, sha1, pre: Vec<u8>);
|
||||
case!("SHA1.sol", SHA1, sha1Call, sha1, pre: Bytes);
|
||||
|
||||
sol!(
|
||||
contract ERC20 {
|
||||
@@ -163,7 +161,7 @@ sol!(
|
||||
function mStore8(uint value) public pure returns (uint256 word);
|
||||
}
|
||||
);
|
||||
case!("mStore8.sol", MStore8, mStore8Call, mstore8, value: U256);
|
||||
case!("MStore8.sol", MStore8, mStore8Call, mstore8, value: U256);
|
||||
|
||||
sol!(
|
||||
contract Events {
|
||||
@@ -190,7 +188,7 @@ sol!(
|
||||
function memcpy(bytes memory payload) public pure returns (bytes memory);
|
||||
}
|
||||
);
|
||||
case!("MCopy.sol", MCopy, memcpyCall, memcpy, payload: Vec<u8>);
|
||||
case!("MCopy.sol", MCopy, memcpyCall, memcpy, payload: Bytes);
|
||||
|
||||
sol!(
|
||||
contract Call {
|
||||
@@ -205,7 +203,7 @@ sol!(
|
||||
}
|
||||
);
|
||||
case!("Call.sol", Call, value_transferCall, call_value_transfer, destination: Address);
|
||||
case!("Call.sol", Call, callCall, call_call, destination: Address, payload: Vec<u8>);
|
||||
case!("Call.sol", Call, callCall, call_call, destination: Address, payload: Bytes);
|
||||
case!("Call.sol", "Call", vec![], call_constructor);
|
||||
|
||||
sol!(
|
||||
@@ -230,24 +228,6 @@ sol!(
|
||||
case!("Storage.sol", Storage, transientCall, storage_transient, value: U256);
|
||||
|
||||
impl Contract {
|
||||
/// Execute the contract.
|
||||
///
|
||||
/// Useful helper if the contract state can be ignored,
|
||||
/// as it spares the deploy transaciton.
|
||||
///
|
||||
/// - Inserts an account with given `code` into a new state.
|
||||
/// - Callee and caller account will be `Transaction::default_address()`.
|
||||
/// - Sets the calldata.
|
||||
/// - Doesn't execute the constructor or deploy code.
|
||||
/// - Calls the "call" export on a default backend config.
|
||||
pub fn execute(&self) -> (State, CallOutput) {
|
||||
State::default()
|
||||
.transaction()
|
||||
.with_default_account(&self.pvm_runtime)
|
||||
.calldata(self.calldata.clone())
|
||||
.call()
|
||||
}
|
||||
|
||||
fn build(calldata: Vec<u8>, name: &'static str, code: &str) -> Self {
|
||||
Self {
|
||||
name,
|
||||
@@ -260,7 +240,7 @@ impl Contract {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use alloy_primitives::U256;
|
||||
use alloy_primitives::{Bytes, U256};
|
||||
use rayon::iter::{IntoParallelIterator, ParallelIterator};
|
||||
use serde::{de::Deserialize, Serialize};
|
||||
use std::{collections::BTreeMap, fs::File};
|
||||
@@ -305,7 +285,7 @@ mod tests {
|
||||
(|| Contract::odd_product(0)) as fn() -> Contract,
|
||||
(|| Contract::fib_iterative(U256::ZERO)) as fn() -> Contract,
|
||||
Contract::erc20 as fn() -> Contract,
|
||||
(|| Contract::sha1(Vec::new())) as fn() -> Contract,
|
||||
(|| Contract::sha1(Bytes::new())) as fn() -> Contract,
|
||||
(|| Contract::division_arithmetics_div(U256::ZERO, U256::ZERO)) as fn() -> Contract,
|
||||
(|| Contract::event(U256::ZERO)) as fn() -> Contract,
|
||||
]
|
||||
|
||||
@@ -1,42 +1,4 @@
|
||||
use alloy_primitives::{Address, U256};
|
||||
use cases::Contract;
|
||||
use mock_runtime::{CallOutput, State};
|
||||
|
||||
use crate::mock_runtime::{Event, ReturnFlags};
|
||||
|
||||
pub mod cases;
|
||||
pub mod mock_runtime;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
pub fn assert_success(contract: &Contract, differential: bool) -> (State, CallOutput) {
|
||||
let (state, output) = contract.execute();
|
||||
assert_eq!(output.flags, ReturnFlags::Success);
|
||||
|
||||
if differential {
|
||||
let evm =
|
||||
revive_differential::prepare(contract.evm_runtime.clone(), contract.calldata.clone());
|
||||
let (evm_output, evm_log) = revive_differential::execute(evm);
|
||||
|
||||
assert_eq!(output.data.clone(), evm_output);
|
||||
assert_eq!(output.events.len(), evm_log.len());
|
||||
assert_eq!(
|
||||
output.events,
|
||||
evm_log
|
||||
.iter()
|
||||
.map(|log| Event {
|
||||
address: Address::from_slice(log.address.as_bytes()),
|
||||
data: log.data.clone(),
|
||||
topics: log
|
||||
.topics
|
||||
.iter()
|
||||
.map(|topic| U256::from_be_bytes(topic.0))
|
||||
.collect(),
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
);
|
||||
}
|
||||
|
||||
(state, output)
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+235
-470
@@ -1,294 +1,257 @@
|
||||
use std::str::FromStr;
|
||||
|
||||
use alloy_primitives::{keccak256, Address, FixedBytes, B256, I256, U256};
|
||||
use alloy_sol_types::{sol, SolCall, SolValue};
|
||||
use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
|
||||
use sha1::Digest;
|
||||
use alloy_primitives::*;
|
||||
use revive_runner::*;
|
||||
use SpecsAction::*;
|
||||
|
||||
use revive_solidity::test_utils::*;
|
||||
use crate::cases::Contract;
|
||||
|
||||
use crate::{
|
||||
assert_success,
|
||||
cases::Contract,
|
||||
mock_runtime::{self, ReturnFlags, State, Transaction},
|
||||
};
|
||||
macro_rules! test_spec {
|
||||
($test_name:ident, $contract_name:literal, $source_file:literal) => {
|
||||
#[test]
|
||||
fn $test_name() {
|
||||
let manifest_dir = std::env::var("CARGO_MANIFEST_DIR").expect("should always exist");
|
||||
let path = format!("{manifest_dir}/../integration/contracts/{}", $source_file);
|
||||
specs_from_comment($contract_name, &path).remove(0).run();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fibonacci() {
|
||||
let parameter = 6;
|
||||
test_spec!(baseline, "Baseline", "Baseline.sol");
|
||||
test_spec!(flipper, "Flipper", "flipper.sol");
|
||||
test_spec!(fibonacci_recursive, "FibonacciRecursive", "Fibonacci.sol");
|
||||
test_spec!(fibonacci_iterative, "FibonacciIterative", "Fibonacci.sol");
|
||||
test_spec!(fibonacci_binet, "FibonacciBinet", "Fibonacci.sol");
|
||||
test_spec!(hash_keccak_256, "TestSha3", "Crypto.sol");
|
||||
test_spec!(erc20, "ERC20", "ERC20.sol");
|
||||
test_spec!(computation, "Computation", "Computation.sol");
|
||||
test_spec!(msize, "MSize", "MSize.sol");
|
||||
test_spec!(transferred_value, "Value", "Value.sol");
|
||||
test_spec!(sha1, "SHA1", "SHA1.sol");
|
||||
test_spec!(block, "Block", "Block.sol");
|
||||
test_spec!(mcopy, "MCopy", "MCopy.sol");
|
||||
test_spec!(events, "Events", "Events.sol");
|
||||
test_spec!(storage, "Storage", "Storage.sol");
|
||||
test_spec!(mstore8, "MStore8", "MStore8.sol");
|
||||
|
||||
for contract in [
|
||||
Contract::fib_recursive(U256::from(parameter)),
|
||||
Contract::fib_iterative(U256::from(parameter)),
|
||||
Contract::fib_binet(U256::from(parameter)),
|
||||
] {
|
||||
let (_, output) = assert_success(&contract, true);
|
||||
let received = U256::from_be_bytes::<32>(output.data.try_into().unwrap());
|
||||
let expected = U256::from(8);
|
||||
assert_eq!(received, expected);
|
||||
fn instantiate(path: &str, contract: &str) -> Vec<SpecsAction> {
|
||||
vec![Instantiate {
|
||||
origin: TestAccountId::Alice,
|
||||
value: 0,
|
||||
gas_limit: Some(GAS_LIMIT),
|
||||
storage_deposit_limit: None,
|
||||
code: Code::Solidity {
|
||||
path: Some(path.into()),
|
||||
contract: contract.to_string(),
|
||||
solc_optimizer: None,
|
||||
pipeline: None,
|
||||
},
|
||||
data: vec![],
|
||||
salt: vec![],
|
||||
}]
|
||||
}
|
||||
|
||||
fn run_differential(actions: Vec<SpecsAction>) {
|
||||
Specs {
|
||||
differential: true,
|
||||
balances: vec![(ALICE, 1_000_000_000)],
|
||||
actions,
|
||||
}
|
||||
.run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn flipper() {
|
||||
let (state, address) = State::new_deployed(Contract::flipper_constructor(true));
|
||||
fn bitwise_byte() {
|
||||
let mut actions = instantiate("contracts/Bitwise.sol", "Bitwise");
|
||||
|
||||
let contract = Contract::flipper();
|
||||
let (state, output) = state
|
||||
.transaction()
|
||||
.calldata(contract.calldata.clone())
|
||||
.callee(address)
|
||||
.call();
|
||||
assert_eq!(output.flags, ReturnFlags::Success);
|
||||
state.assert_storage_key(address, U256::ZERO, U256::ZERO);
|
||||
|
||||
let (state, output) = state
|
||||
.transaction()
|
||||
.calldata(contract.calldata)
|
||||
.callee(address)
|
||||
.call();
|
||||
assert_eq!(output.flags, ReturnFlags::Success);
|
||||
state.assert_storage_key(address, U256::ZERO, U256::from(1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hash_keccak_256() {
|
||||
sol!(
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
contract TestSha3 {
|
||||
function test(string memory _pre) external payable returns (bytes32);
|
||||
}
|
||||
);
|
||||
let source = r#"contract TestSha3 {
|
||||
function test(string memory _pre) external payable returns (bytes32 hash) {
|
||||
hash = keccak256(bytes(_pre));
|
||||
}
|
||||
}"#;
|
||||
let code = compile_blob("TestSha3", source);
|
||||
|
||||
let param = "hello";
|
||||
let input = TestSha3::testCall::new((param.to_string(),)).abi_encode();
|
||||
|
||||
let (_, output) = State::default()
|
||||
.transaction()
|
||||
.with_default_account(&code)
|
||||
.calldata(input)
|
||||
.call();
|
||||
|
||||
assert_eq!(output.flags, ReturnFlags::Success);
|
||||
|
||||
let expected = keccak256(param.as_bytes());
|
||||
let received = FixedBytes::<32>::from_slice(&output.data);
|
||||
assert_eq!(received, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn erc20() {
|
||||
let _ = compile_blob("ERC20", include_str!("../contracts/ERC20.sol"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn triangle_number() {
|
||||
let (_, output) = assert_success(&Contract::triangle_number(13), true);
|
||||
let received = U256::from_be_bytes::<32>(output.data.try_into().unwrap());
|
||||
let expected = U256::try_from(91).unwrap();
|
||||
assert_eq!(received, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn odd_product() {
|
||||
let (_, output) = assert_success(&Contract::odd_product(5), true);
|
||||
let received = I256::from_be_bytes::<32>(output.data.try_into().unwrap());
|
||||
let expected = I256::try_from(945i64).unwrap();
|
||||
assert_eq!(received, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn msize_plain() {
|
||||
sol!(
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
contract MSize {
|
||||
function mSize() public pure returns (uint);
|
||||
}
|
||||
);
|
||||
let code = compile_blob_with_options(
|
||||
"MSize",
|
||||
include_str!("../contracts/MSize.sol"),
|
||||
false,
|
||||
revive_solidity::SolcPipeline::EVMLA,
|
||||
);
|
||||
|
||||
let input = MSize::mSizeCall::new(()).abi_encode();
|
||||
let (_, output) = State::default()
|
||||
.transaction()
|
||||
.calldata(input)
|
||||
.with_default_account(&code)
|
||||
.call();
|
||||
|
||||
assert_eq!(output.flags, ReturnFlags::Success);
|
||||
|
||||
// Solidity always stores the "free memory pointer" (32 byte int) at offset 64.
|
||||
let expected = U256::try_from(64 + 32).unwrap();
|
||||
let received = U256::from_be_bytes::<32>(output.data.try_into().unwrap());
|
||||
assert_eq!(received, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn transferred_value() {
|
||||
sol!(
|
||||
contract Value {
|
||||
function value() public payable returns (uint);
|
||||
}
|
||||
);
|
||||
let code = compile_blob("Value", include_str!("../contracts/Value.sol"));
|
||||
|
||||
let (_, output) = State::default()
|
||||
.transaction()
|
||||
.calldata(Value::valueCall::SELECTOR.to_vec())
|
||||
.callvalue(U256::from(123))
|
||||
.with_default_account(&code)
|
||||
.call();
|
||||
|
||||
assert_eq!(output.flags, ReturnFlags::Success);
|
||||
|
||||
let expected = I256::try_from(123).unwrap();
|
||||
let received = I256::from_be_bytes::<32>(output.data.try_into().unwrap());
|
||||
assert_eq!(received, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn msize_non_word_sized_access() {
|
||||
sol!(
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
contract MSize {
|
||||
function mStore100() public pure returns (uint);
|
||||
}
|
||||
);
|
||||
let code = compile_blob_with_options(
|
||||
"MSize",
|
||||
include_str!("../contracts/MSize.sol"),
|
||||
false,
|
||||
revive_solidity::SolcPipeline::Yul,
|
||||
);
|
||||
|
||||
let input = MSize::mStore100Call::new(()).abi_encode();
|
||||
let (_, output) = State::default()
|
||||
.transaction()
|
||||
.with_default_account(&code)
|
||||
.calldata(input)
|
||||
.call();
|
||||
|
||||
assert_eq!(output.flags, ReturnFlags::Success);
|
||||
|
||||
// https://docs.zksync.io/build/developer-reference/differences-with-ethereum.html#mstore-mload
|
||||
// "Unlike EVM, where the memory growth is in words, on zkEVM the memory growth is counted in bytes."
|
||||
// "For example, if you write mstore(100, 0) the msize on zkEVM will be 132, but on the EVM it will be 160."
|
||||
let expected = U256::try_from(132).unwrap();
|
||||
let received = U256::from_be_bytes::<32>(output.data.try_into().unwrap());
|
||||
assert_eq!(received, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mstore8() {
|
||||
for (received, expected) in [
|
||||
(U256::MIN, U256::MIN),
|
||||
(
|
||||
U256::from(1),
|
||||
U256::from_str_radix(
|
||||
"452312848583266388373324160190187140051835877600158453279131187530910662656",
|
||||
10,
|
||||
)
|
||||
.unwrap(),
|
||||
),
|
||||
(
|
||||
U256::from(2),
|
||||
U256::from_str_radix(
|
||||
"904625697166532776746648320380374280103671755200316906558262375061821325312",
|
||||
10,
|
||||
)
|
||||
.unwrap(),
|
||||
),
|
||||
(
|
||||
U256::from(255),
|
||||
U256::from_str_radix(
|
||||
"115339776388732929035197660848497720713218148788040405586178452820382218977280",
|
||||
10,
|
||||
)
|
||||
.unwrap(),
|
||||
),
|
||||
(U256::from(256), U256::from(0)),
|
||||
(
|
||||
U256::from(257),
|
||||
U256::from_str_radix(
|
||||
"452312848583266388373324160190187140051835877600158453279131187530910662656",
|
||||
10,
|
||||
)
|
||||
.unwrap(),
|
||||
),
|
||||
(
|
||||
U256::from(258),
|
||||
U256::from_str_radix(
|
||||
"904625697166532776746648320380374280103671755200316906558262375061821325312",
|
||||
10,
|
||||
)
|
||||
.unwrap(),
|
||||
),
|
||||
(
|
||||
U256::from(123456789),
|
||||
U256::from_str_radix(
|
||||
"9498569820248594155839807363993929941088553429603327518861754938149123915776",
|
||||
10,
|
||||
)
|
||||
.unwrap(),
|
||||
),
|
||||
(
|
||||
U256::MAX,
|
||||
U256::from_str_radix(
|
||||
"115339776388732929035197660848497720713218148788040405586178452820382218977280",
|
||||
10,
|
||||
)
|
||||
.unwrap(),
|
||||
),
|
||||
]
|
||||
.par_iter()
|
||||
.map(|(parameter, expected)| {
|
||||
let (_, output) = assert_success(&Contract::mstore8(*parameter), true);
|
||||
let received = U256::from_be_bytes::<32>(output.data.try_into().unwrap());
|
||||
(received, *expected)
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
let de_bruijn_sequence =
|
||||
hex::decode("4060503824160d0784426150b864361d0f88c4a27148ac5a2f198d46e391d8f4").unwrap();
|
||||
let value = U256::from_be_bytes::<32>(de_bruijn_sequence.clone().try_into().unwrap());
|
||||
for input in de_bruijn_sequence
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(index, _)| Contract::bitwise_byte(U256::from(index), value).calldata)
|
||||
.chain([
|
||||
Contract::bitwise_byte(U256::ZERO, U256::ZERO).calldata,
|
||||
Contract::bitwise_byte(U256::ZERO, U256::MAX).calldata,
|
||||
Contract::bitwise_byte(U256::MAX, U256::ZERO).calldata,
|
||||
Contract::bitwise_byte(U256::from_str("18446744073709551619").unwrap(), U256::MAX)
|
||||
.calldata,
|
||||
])
|
||||
{
|
||||
assert_eq!(received, expected);
|
||||
actions.push(Call {
|
||||
origin: TestAccountId::Alice,
|
||||
dest: TestAccountId::Instantiated(0),
|
||||
value: 0,
|
||||
gas_limit: None,
|
||||
storage_deposit_limit: None,
|
||||
data: input,
|
||||
})
|
||||
}
|
||||
|
||||
run_differential(actions);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unsigned_division() {
|
||||
let mut actions = instantiate("contracts/DivisionArithmetics.sol", "DivisionArithmetics");
|
||||
|
||||
let one = U256::from(1);
|
||||
let two = U256::from(2);
|
||||
let five = U256::from(5);
|
||||
for (n, d) in [
|
||||
(five, five),
|
||||
(five, one),
|
||||
(U256::ZERO, U256::MAX),
|
||||
(five, two),
|
||||
(one, U256::ZERO),
|
||||
] {
|
||||
actions.push(Call {
|
||||
origin: TestAccountId::Alice,
|
||||
dest: TestAccountId::Instantiated(0),
|
||||
value: 0,
|
||||
gas_limit: None,
|
||||
storage_deposit_limit: None,
|
||||
data: Contract::division_arithmetics_div(n, d).calldata,
|
||||
})
|
||||
}
|
||||
|
||||
run_differential(actions);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn signed_division() {
|
||||
let mut actions = instantiate("contracts/DivisionArithmetics.sol", "DivisionArithmetics");
|
||||
|
||||
let one = I256::try_from(1).unwrap();
|
||||
let two = I256::try_from(2).unwrap();
|
||||
let minus_two = I256::try_from(-2).unwrap();
|
||||
let five = I256::try_from(5).unwrap();
|
||||
let minus_five = I256::try_from(-5).unwrap();
|
||||
for (n, d) in [
|
||||
(five, five),
|
||||
(five, one),
|
||||
(I256::ZERO, I256::MAX),
|
||||
(I256::ZERO, I256::MINUS_ONE),
|
||||
(five, two),
|
||||
(five, I256::MINUS_ONE),
|
||||
(I256::MINUS_ONE, minus_two),
|
||||
(minus_five, minus_five),
|
||||
(minus_five, two),
|
||||
(I256::MINUS_ONE, I256::MIN),
|
||||
(one, I256::ZERO),
|
||||
] {
|
||||
actions.push(Call {
|
||||
origin: TestAccountId::Alice,
|
||||
dest: TestAccountId::Instantiated(0),
|
||||
value: 0,
|
||||
gas_limit: None,
|
||||
storage_deposit_limit: None,
|
||||
data: Contract::division_arithmetics_sdiv(n, d).calldata,
|
||||
})
|
||||
}
|
||||
|
||||
run_differential(actions);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unsigned_remainder() {
|
||||
let mut actions = instantiate("contracts/DivisionArithmetics.sol", "DivisionArithmetics");
|
||||
|
||||
let one = U256::from(1);
|
||||
let two = U256::from(2);
|
||||
let five = U256::from(5);
|
||||
for (n, d) in [
|
||||
(five, five),
|
||||
(five, one),
|
||||
(U256::ZERO, U256::MAX),
|
||||
(U256::MAX, U256::MAX),
|
||||
(five, two),
|
||||
(two, five),
|
||||
(U256::MAX, U256::ZERO),
|
||||
] {
|
||||
actions.push(Call {
|
||||
origin: TestAccountId::Alice,
|
||||
dest: TestAccountId::Instantiated(0),
|
||||
value: 0,
|
||||
gas_limit: None,
|
||||
storage_deposit_limit: None,
|
||||
data: Contract::division_arithmetics_mod(n, d).calldata,
|
||||
})
|
||||
}
|
||||
|
||||
run_differential(actions);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn signed_remainder() {
|
||||
let mut actions = instantiate("contracts/DivisionArithmetics.sol", "DivisionArithmetics");
|
||||
|
||||
let one = I256::try_from(1).unwrap();
|
||||
let two = I256::try_from(2).unwrap();
|
||||
let minus_two = I256::try_from(-2).unwrap();
|
||||
let five = I256::try_from(5).unwrap();
|
||||
let minus_five = I256::try_from(-5).unwrap();
|
||||
for (n, d) in [
|
||||
(five, five),
|
||||
(five, one),
|
||||
(I256::ZERO, I256::MAX),
|
||||
(I256::MAX, I256::MAX),
|
||||
(five, two),
|
||||
(two, five),
|
||||
(five, minus_five),
|
||||
(five, I256::MINUS_ONE),
|
||||
(five, minus_two),
|
||||
(minus_five, two),
|
||||
(minus_two, five),
|
||||
(minus_five, minus_five),
|
||||
(minus_five, I256::MINUS_ONE),
|
||||
(minus_five, minus_two),
|
||||
(minus_two, minus_five),
|
||||
(I256::MIN, I256::MINUS_ONE),
|
||||
(I256::ZERO, I256::ZERO),
|
||||
] {
|
||||
actions.push(Call {
|
||||
origin: TestAccountId::Alice,
|
||||
dest: TestAccountId::Instantiated(0),
|
||||
value: 0,
|
||||
gas_limit: None,
|
||||
storage_deposit_limit: None,
|
||||
data: Contract::division_arithmetics_smod(n, d).calldata,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
#[test]
|
||||
fn sha1() {
|
||||
let pre = vec![0xffu8; 512];
|
||||
let mut hasher = sha1::Sha1::new();
|
||||
hasher.update(&pre);
|
||||
let hash = hasher.finalize();
|
||||
|
||||
let (_, output) = assert_success(&Contract::sha1(pre), true);
|
||||
let expected = FixedBytes::<20>::from_slice(&hash[..]);
|
||||
let received = FixedBytes::<20>::from_slice(&output.data[..20]);
|
||||
assert_eq!(received, expected);
|
||||
fn events() {
|
||||
assert_success(&Contract::event(U256::ZERO), true);
|
||||
assert_success(&Contract::event(U256::from(123)), true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn block_number() {
|
||||
let (_, output) = assert_success(&Contract::block_number(), true);
|
||||
let received = U256::from_be_bytes::<32>(output.data.try_into().unwrap());
|
||||
let expected = U256::from(mock_runtime::State::BLOCK_NUMBER);
|
||||
assert_eq!(received, expected);
|
||||
}
|
||||
fn balance() {
|
||||
let (_, output) = assert_success(&Contract::value_balance_of(Default::default()), false);
|
||||
|
||||
#[test]
|
||||
fn block_timestamp() {
|
||||
let (_, output) = assert_success(&Contract::block_timestamp(), true);
|
||||
let received = U256::from_be_bytes::<32>(output.data.try_into().unwrap());
|
||||
let expected = U256::from(mock_runtime::State::BLOCK_TIMESTAMP);
|
||||
assert_eq!(received, expected);
|
||||
let expected = U256::ZERO;
|
||||
let received = U256::from_be_slice(&output.data);
|
||||
assert_eq!(expected, received);
|
||||
|
||||
let expected = U256::from(54589);
|
||||
let (mut state, address) = State::new_deployed(Contract::value_balance_of(Default::default()));
|
||||
state.accounts_mut().get_mut(&address).unwrap().value = expected;
|
||||
|
||||
let contract = Contract::value_balance_of(address);
|
||||
let (_, output) = state
|
||||
.transaction()
|
||||
.with_default_account(&contract.pvm_runtime)
|
||||
.calldata(contract.calldata)
|
||||
.call();
|
||||
|
||||
assert_eq!(ReturnFlags::Success, output.flags);
|
||||
|
||||
let received = U256::from_be_slice(&output.data);
|
||||
assert_eq!(expected, received)
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -308,132 +271,6 @@ fn caller() {
|
||||
assert_eq!(received, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unsigned_division() {
|
||||
let one = U256::from(1);
|
||||
let two = U256::from(2);
|
||||
let five = U256::from(5);
|
||||
for (received, expected) in [
|
||||
(five, five, one),
|
||||
(five, one, five),
|
||||
(U256::ZERO, U256::MAX, U256::ZERO),
|
||||
(five, two, two),
|
||||
(one, U256::ZERO, U256::ZERO),
|
||||
]
|
||||
.par_iter()
|
||||
.map(|(n, d, q)| {
|
||||
let (_, output) = assert_success(&Contract::division_arithmetics_div(*n, *d), true);
|
||||
let received = U256::from_be_bytes::<32>(output.data.try_into().unwrap());
|
||||
(received, *q)
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
{
|
||||
assert_eq!(received, expected)
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn signed_division() {
|
||||
let one = I256::try_from(1).unwrap();
|
||||
let two = I256::try_from(2).unwrap();
|
||||
let minus_two = I256::try_from(-2).unwrap();
|
||||
let five = I256::try_from(5).unwrap();
|
||||
let minus_five = I256::try_from(-5).unwrap();
|
||||
for (received, expected) in [
|
||||
(five, five, one),
|
||||
(five, one, five),
|
||||
(I256::ZERO, I256::MAX, I256::ZERO),
|
||||
(I256::ZERO, I256::MINUS_ONE, I256::ZERO),
|
||||
(five, two, two),
|
||||
(five, I256::MINUS_ONE, minus_five),
|
||||
(I256::MINUS_ONE, minus_two, I256::ZERO),
|
||||
(minus_five, minus_five, one),
|
||||
(minus_five, two, minus_two),
|
||||
(I256::MINUS_ONE, I256::MIN, I256::ZERO),
|
||||
(one, I256::ZERO, I256::ZERO),
|
||||
]
|
||||
.par_iter()
|
||||
.map(|(n, d, q)| {
|
||||
let (_, output) = assert_success(&Contract::division_arithmetics_sdiv(*n, *d), true);
|
||||
let received = I256::from_be_bytes::<32>(output.data.try_into().unwrap());
|
||||
(received, *q)
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
{
|
||||
assert_eq!(received, expected);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unsigned_remainder() {
|
||||
let one = U256::from(1);
|
||||
let two = U256::from(2);
|
||||
let five = U256::from(5);
|
||||
for (received, expected) in [
|
||||
(five, five, U256::ZERO),
|
||||
(five, one, U256::ZERO),
|
||||
(U256::ZERO, U256::MAX, U256::ZERO),
|
||||
(U256::MAX, U256::MAX, U256::ZERO),
|
||||
(five, two, one),
|
||||
(two, five, two),
|
||||
(U256::MAX, U256::ZERO, U256::ZERO),
|
||||
]
|
||||
.par_iter()
|
||||
.map(|(n, d, q)| {
|
||||
let (_, output) = assert_success(&Contract::division_arithmetics_mod(*n, *d), true);
|
||||
let received = U256::from_be_bytes::<32>(output.data.try_into().unwrap());
|
||||
(received, *q)
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
{
|
||||
assert_eq!(received, expected);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn signed_remainder() {
|
||||
let one = I256::try_from(1).unwrap();
|
||||
let two = I256::try_from(2).unwrap();
|
||||
let minus_two = I256::try_from(-2).unwrap();
|
||||
let five = I256::try_from(5).unwrap();
|
||||
let minus_five = I256::try_from(-5).unwrap();
|
||||
for (received, expected) in [
|
||||
(five, five, I256::ZERO),
|
||||
(five, one, I256::ZERO),
|
||||
(I256::ZERO, I256::MAX, I256::ZERO),
|
||||
(I256::MAX, I256::MAX, I256::ZERO),
|
||||
(five, two, one),
|
||||
(two, five, two),
|
||||
(five, minus_five, I256::ZERO),
|
||||
(five, I256::MINUS_ONE, I256::ZERO),
|
||||
(five, minus_two, one),
|
||||
(minus_five, two, I256::MINUS_ONE),
|
||||
(minus_two, five, minus_two),
|
||||
(minus_five, minus_five, I256::ZERO),
|
||||
(minus_five, I256::MINUS_ONE, I256::ZERO),
|
||||
(minus_five, minus_two, I256::MINUS_ONE),
|
||||
(minus_two, minus_five, minus_two),
|
||||
(I256::MIN, I256::MINUS_ONE, I256::ZERO),
|
||||
(I256::ZERO, I256::ZERO, I256::ZERO),
|
||||
]
|
||||
.par_iter()
|
||||
.map(|(n, d, q)| {
|
||||
let (_, output) = assert_success(&Contract::division_arithmetics_smod(*n, *d), true);
|
||||
let received = I256::from_be_bytes::<32>(output.data.try_into().unwrap());
|
||||
(received, *q)
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
{
|
||||
assert_eq!(received, expected);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn events() {
|
||||
assert_success(&Contract::event(U256::ZERO), true);
|
||||
assert_success(&Contract::event(U256::from(123)), true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn create2() {
|
||||
let mut state = State::default();
|
||||
@@ -565,76 +402,4 @@ fn echo() {
|
||||
|
||||
assert_eq!(expected, received);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mcopy() {
|
||||
let expected = vec![1, 2, 3];
|
||||
|
||||
let (_, output) = assert_success(&Contract::memcpy(expected.clone()), false);
|
||||
|
||||
let received = alloy_primitives::Bytes::abi_decode(&output.data, true)
|
||||
.unwrap()
|
||||
.to_vec();
|
||||
|
||||
assert_eq!(expected, received);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn balance() {
|
||||
let (_, output) = assert_success(&Contract::value_balance_of(Default::default()), false);
|
||||
|
||||
let expected = U256::ZERO;
|
||||
let received = U256::from_be_slice(&output.data);
|
||||
assert_eq!(expected, received);
|
||||
|
||||
let expected = U256::from(54589);
|
||||
let (mut state, address) = State::new_deployed(Contract::value_balance_of(Default::default()));
|
||||
state.accounts_mut().get_mut(&address).unwrap().value = expected;
|
||||
|
||||
let contract = Contract::value_balance_of(address);
|
||||
let (_, output) = state
|
||||
.transaction()
|
||||
.with_default_account(&contract.pvm_runtime)
|
||||
.calldata(contract.calldata)
|
||||
.call();
|
||||
|
||||
assert_eq!(ReturnFlags::Success, output.flags);
|
||||
|
||||
let received = U256::from_be_slice(&output.data);
|
||||
assert_eq!(expected, received)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bitwise_byte() {
|
||||
assert_success(&Contract::bitwise_byte(U256::ZERO, U256::ZERO), true);
|
||||
assert_success(&Contract::bitwise_byte(U256::ZERO, U256::MAX), true);
|
||||
assert_success(&Contract::bitwise_byte(U256::MAX, U256::ZERO), true);
|
||||
assert_success(
|
||||
&Contract::bitwise_byte(U256::from_str("18446744073709551619").unwrap(), U256::MAX),
|
||||
true,
|
||||
);
|
||||
|
||||
let de_bruijn_sequence =
|
||||
hex::decode("4060503824160d0784426150b864361d0f88c4a27148ac5a2f198d46e391d8f4").unwrap();
|
||||
let value = U256::from_be_bytes::<32>(de_bruijn_sequence.clone().try_into().unwrap());
|
||||
|
||||
for (index, byte) in de_bruijn_sequence.iter().enumerate() {
|
||||
let (_, output) = assert_success(&Contract::bitwise_byte(U256::from(index), value), true);
|
||||
let expected = U256::from(*byte as i32);
|
||||
let received = U256::abi_decode(&output.data, true).unwrap();
|
||||
assert_eq!(expected, received)
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn transient_storage() {
|
||||
let expected = U256::MAX;
|
||||
let (state, output) = assert_success(&Contract::storage_transient(expected), false);
|
||||
let received = U256::abi_decode(&output.data, true).unwrap();
|
||||
assert_eq!(expected, received);
|
||||
|
||||
assert!(state
|
||||
.accounts()
|
||||
.values()
|
||||
.all(|account| account.storage.is_empty()));
|
||||
}
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user