Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/forest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,7 @@ jobs:
forest-dev tests mpool
forest-dev tests wallet
forest-dev devnet eth-gas
forest-dev devnet eth-skip-sender
timeout-minutes: ${{ fromJSON(env.SCRIPT_TIMEOUT_MINUTES) }}
- name: Dump docker logs
if: always()
Expand Down
1 change: 1 addition & 0 deletions mise.toml
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,7 @@ devnet_test_env_init
forest-dev tests mpool
forest-dev tests wallet
forest-dev devnet eth-gas
forest-dev devnet eth-skip-sender
'''

[tasks."codecov:nextest"]
Expand Down
14 changes: 8 additions & 6 deletions scripts/devnet/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,9 @@ forest-cli net peers
## Running the integration tests

The wallet/mpool suites that run against calibnet, plus the `eth_estimateGas`
parity suite, can be run against the local devnet. This brings up the devnet,
waits for it to sync, wires up the host environment, and runs the tests:
parity suite and the skip-sender integration tests, can be run against the local
devnet. This brings up the devnet, waits for it to sync, wires up the host
environment, and runs the tests:

```shell
mise run test:devnet
Expand All @@ -69,12 +70,13 @@ mise run test:devnet
Under the hood this sources `test_harness.sh`, which reads the admin token and
the funded genesis key from the running `forest` container, exports
`FULLNODE_API_INFO` (Forest RPC on port 3456) and `FOREST_TEST_PRELOADED_ADDRESS`,
then runs `forest-dev tests mpool`, `forest-dev tests wallet` and
`forest-dev devnet eth-gas`.
then runs `forest-dev tests mpool`, `forest-dev tests wallet`,
`forest-dev devnet eth-gas` and `forest-dev devnet eth-skip-sender`.

The `devnet` suites (unlike `tests`) need both nodes reachable: `eth-gas`
compares Forest against Lotus, so it runs pre-flight checks and fails early if
the devnet or harness environment is missing.
compares Forest against Lotus, and `eth-skip-sender` deploys contracts and
submits transactions, so they run pre-flight checks and fail early if the
devnet or harness environment is missing.

## Local devnet development

Expand Down
2 changes: 1 addition & 1 deletion scripts/devnet/test_harness.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/bin/bash
# Sourced (not executed) helpers for the devnet test suites (wallet, mpool,
# eth-gas) on the docker devnet. Run after the devnet is up (`setup.sh`) and synced (`check.sh`).
# eth-gas, eth-skip-sender) on the docker devnet. Run after the devnet is up (`setup.sh`) and synced (`check.sh`).
#
# The genesis key is the Lotus miner's default wallet, so using it as the test
# sender causes nonce contention. We fund a dedicated wallet instead.
Expand Down
3 changes: 3 additions & 0 deletions src/dev/subcommands/devnet_cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
//! that environment is missing, rather than letting a suite surface it as an opaque mid-run error.

mod eth_gas;
mod eth_skip_sender;

use crate::dev::subcommands::tests_cmd::helpers::{docker, forest_client, lotus_client};
use crate::rpc::prelude::*;
Expand All @@ -16,13 +17,15 @@ use anyhow::{Context as _, ensure};
#[derive(Debug, clap::Subcommand)]
pub enum DevnetCommand {
EthGas(eth_gas::EthGasTestCommand),
EthSkipSender(eth_skip_sender::EthSkipSenderTestCommand),
}

impl DevnetCommand {
pub async fn run(self) -> anyhow::Result<()> {
preflight().await.context("devnet pre-flight failed")?;
match self {
Self::EthGas(cmd) => cmd.run().await,
Self::EthSkipSender(cmd) => cmd.run().await,
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/dev/subcommands/devnet_cmd/contracts/compile.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@ for sol in "${DIR}"/*/*.sol; do
echo "compiling ${name} with solc ${SOLC_VERSION}"
docker run --rm --volume "${contract_dir}:/src:ro" "ethereum/solc:${SOLC_VERSION}" \
--bin "/src/${name}.sol" |
awk '/^Binary:/ { getline; print }' > "${contract_dir}/${name}.hex"
awk '/^Binary:/ { getline; if ($0 != "") print }' > "${contract_dir}/${name}.hex"
done
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
6080604052348015600e575f5ffd5b50602a5f81905550610506806100235f395ff3fe608060405234801561000f575f5ffd5b5060043610610086575f3560e01c8063893885081161005957806389388508146100fe5780639ff8a3681461011c578063a70c52381461013a578063d1accab81461015857610086565b8063209652551461008a578063224bc07f146100a857806355241077146100c45780636d619daa146100e0575b5f5ffd5b610092610176565b60405161009f9190610372565b60405180910390f35b6100c260048036038101906100bd91906103e9565b61017e565b005b6100de60048036038101906100d9919061043e565b6101c1565b005b6100e86101ca565b6040516100f59190610372565b60405180910390f35b6101066101cf565b6040516101139190610372565b60405180910390f35b61012461026e565b6040516101319190610478565b60405180910390f35b610142610293565b60405161014f9190610372565b60405180910390f35b610160610332565b60405161016d9190610478565b60405180910390f35b5f5f54905090565b8060015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b805f8190555050565b5f5481565b5f60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f2e2b693306040518263ffffffff1660e01b815260040161022a9190610478565b602060405180830381865afa158015610245573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061026991906104a5565b905090565b60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166317dbce79306040518263ffffffff1660e01b81526004016102ee9190610478565b602060405180830381865afa158015610309573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061032d91906104a5565b905090565b5f60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b5f819050919050565b61036c8161035a565b82525050565b5f6020820190506103855f830184610363565b92915050565b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6103b88261038f565b9050919050565b6103c8816103ae565b81146103d2575f5ffd5b50565b5f813590506103e3816103bf565b92915050565b5f602082840312156103fe576103fd61038b565b5b5f61040b848285016103d5565b91505092915050565b61041d8161035a565b8114610427575f5ffd5b50565b5f8135905061043881610414565b92915050565b5f602082840312156104535761045261038b565b5b5f6104608482850161042a565b91505092915050565b610472816103ae565b82525050565b5f60208201905061048b5f830184610469565b92915050565b5f8151905061049f81610414565b92915050565b5f602082840312156104ba576104b961038b565b5b5f6104c784828501610491565b9150509291505056fea264697066735822122072a88324061d97eecf334e91d04262f4de9c4bea40c9ae7f7b0bc5a6fbacf60364736f6c634300081e0033
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// SPDX-License-Identifier: MIT
pragma solidity =0.8.30;

/// Lotus `itests/contracts/ContractA.sol`, pinned to the compiler this
/// directory's `compile.sh` uses. Calls into ContractB, which calls back here.

// Interface for ContractB
interface IContractB {
function callBackAndRead(address origin) external view returns (uint256);
function callBackAndDouble(address origin) external view returns (uint256);
}

// ContractA: Has state and can call ContractB which calls back
contract ContractA {
Comment thread
sudo-shashank marked this conversation as resolved.
uint256 public storedValue;
address public contractB;

constructor() {
storedValue = 42;
}

// Sets the ContractB address (called after deployment)
function setContractB(address _contractB) external {
contractB = _contractB;
}

// Simple view function that ContractB will call back
function getValue() external view returns (uint256) {
return storedValue;
}

// Sets a new value
function setValue(uint256 _value) external {
storedValue = _value;
}

// Calls ContractB, which calls back to this contract's getValue()
// This tests: A calls B, B calls A.getValue() (view)
function callBAndReadBack() external view returns (uint256) {
return IContractB(contractB).callBackAndRead(address(this));
}

// Calls ContractB, which reads and doubles our value
function callBAndDouble() external view returns (uint256) {
return IContractB(contractB).callBackAndDouble(address(this));
}

// Returns the ContractB address for verification
function getContractB() external view returns (address) {
return contractB;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
6080604052348015600e575f5ffd5b506103468061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610034575f3560e01c806317dbce7914610038578063f2e2b69314610068575b5f5ffd5b610052600480360381019061004d91906101f1565b610098565b60405161005f9190610234565b60405180910390f35b610082600480360381019061007d91906101f1565b61010d565b60405161008f9190610234565b60405180910390f35b5f8173ffffffffffffffffffffffffffffffffffffffff1663209652556040518163ffffffff1660e01b8152600401602060405180830381865afa1580156100e2573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906101069190610277565b9050919050565b5f5f8273ffffffffffffffffffffffffffffffffffffffff1663209652556040518163ffffffff1660e01b8152600401602060405180830381865afa158015610158573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061017c9190610277565b905060028161018b91906102cf565b915050919050565b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6101c082610197565b9050919050565b6101d0816101b6565b81146101da575f5ffd5b50565b5f813590506101eb816101c7565b92915050565b5f6020828403121561020657610205610193565b5b5f610213848285016101dd565b91505092915050565b5f819050919050565b61022e8161021c565b82525050565b5f6020820190506102475f830184610225565b92915050565b6102568161021c565b8114610260575f5ffd5b50565b5f815190506102718161024d565b92915050565b5f6020828403121561028c5761028b610193565b5b5f61029984828501610263565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6102d98261021c565b91506102e48361021c565b92508282026102f28161021c565b91508282048414831517610309576103086102a2565b5b509291505056fea26469706673582212209f90fdacf5ee509e35cfe0923fc7e3e613a96f57ab595450e04777c0fe202c4064736f6c634300081e0033
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// SPDX-License-Identifier: MIT
pragma solidity =0.8.30;

/// Lotus `itests/contracts/ContractB.sol`, pinned to the compiler this
/// directory's `compile.sh` uses. Callback target for ContractA skip-sender tests.

// Interface for ContractA (used by ContractB to call back)
interface IContractA {
function getValue() external view returns (uint256);
}

// ContractB: Receives a call and calls back to the origin contract's view function
contract ContractB {
// Calls back to the provided contract address and reads its getValue()
function callBackAndRead(address origin) external view returns (uint256) {
return IContractA(origin).getValue();
}

// Calls back to origin, reads value, and returns double
function callBackAndDouble(address origin) external view returns (uint256) {
uint256 val = IContractA(origin).getValue();
return val * 2;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
6080604052348015600e575f5ffd5b506102cc8061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610055575f3560e01c80630abe88b61461005957806358d4cbce1461006357806359be8c551461006d5780638791bd3314610077578063c6dbcf2e14610081575b5f5ffd5b61006161008b565b005b61006b61009b565b005b61007561009f565b005b61007f6100da565b005b61008961010c565b005b5f61009957610098610126565b5b565b5f5ffd5b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100d1906101ad565b60405180910390fd5b6040517f09caebf300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f600190505f5f90508082610121919061022e565b505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52600160045260245ffd5b5f82825260208201905092915050565b7f6d7920726561736f6e00000000000000000000000000000000000000000000005f82015250565b5f610197600983610153565b91506101a282610163565b602082019050919050565b5f6020820190508181035f8301526101c48161018b565b9050919050565b5f819050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f610238826101cb565b9150610243836101cb565b925082610253576102526101d4565b5b60015f0383147f80000000000000000000000000000000000000000000000000000000000000008314161561028b5761028a610201565b5b82820590509291505056fea2646970667358221220544d83bfa77064090f1818996be89f2496e4c52cb66b84772263812b623ec21064736f6c634300081e0033
31 changes: 31 additions & 0 deletions src/dev/subcommands/devnet_cmd/contracts/errors/errors.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// SPDX-License-Identifier: MIT
pragma solidity =0.8.30;

/// Lotus `itests/contracts/Errors.sol`, pinned to the compiler this
/// directory's `compile.sh` uses. Skip-sender revert tests call these methods
/// to pin JSON-RPC code, decoded reason, and revert data.
contract Errors {
error CustomError();

function failRevertEmpty() public {
revert();
}

function failRevertReason() public {
revert("my reason");
}

function failAssert() public {
assert(false);
}

function failDivZero() public {
int a = 1;
int b = 0;
a / b;
}

function failCustom() public {
revert CustomError();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
6080604052348015600e575f5ffd5b506127105f5f3273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055506104f58061005f5f395ff3fe608060405234801561000f575f5ffd5b506004361061003f575f3560e01c80637bd703e81461004357806390b98a1114610073578063f8b2cb4f146100a3575b5f5ffd5b61005d600480360381019061005891906102f4565b6100d3565b60405161006a9190610337565b60405180910390f35b61008d6004803603810190610088919061037a565b6100f0565b60405161009a91906103d2565b60405180910390f35b6100bd60048036038101906100b891906102f4565b610251565b6040516100ca9190610337565b60405180910390f35b5f60026100df83610251565b6100e99190610418565b9050919050565b5f815f5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054101561013d575f905061024b565b815f5f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546101889190610459565b92505081905550815f5f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546101da919061048c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161023e9190610337565b60405180910390a3600190505b92915050565b5f5f5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050919050565b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6102c38261029a565b9050919050565b6102d3816102b9565b81146102dd575f5ffd5b50565b5f813590506102ee816102ca565b92915050565b5f6020828403121561030957610308610296565b5b5f610316848285016102e0565b91505092915050565b5f819050919050565b6103318161031f565b82525050565b5f60208201905061034a5f830184610328565b92915050565b6103598161031f565b8114610363575f5ffd5b50565b5f8135905061037481610350565b92915050565b5f5f604083850312156103905761038f610296565b5b5f61039d858286016102e0565b92505060206103ae85828601610366565b9150509250929050565b5f8115159050919050565b6103cc816103b8565b82525050565b5f6020820190506103e55f8301846103c3565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6104228261031f565b915061042d8361031f565b925082820261043b8161031f565b91508282048414831517610452576104516103eb565b5b5092915050565b5f6104638261031f565b915061046e8361031f565b9250828203905081811115610486576104856103eb565b5b92915050565b5f6104968261031f565b91506104a18361031f565b92508282019050808211156104b9576104b86103eb565b5b9291505056fea2646970667358221220e0cfde66801b2ecaad214997e30ea2fcb10e4b212161c6554ca5e157310214d264736f6c634300081e0033
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// SPDX-License-Identifier: MIT
pragma solidity =0.8.30;

/// Lotus `itests/contracts/SimpleCoin.sol`, pinned to the compiler this
/// directory's `compile.sh` uses. `sendCoin` returns whether `balances[msg.sender]`
/// covered the amount, so a skip-sender `eth_call` can report the requested `from`.
contract SimpleCoin {
mapping(address => uint256) balances;

event Transfer(address indexed _from, address indexed _to, uint256 _value);

constructor() {
balances[tx.origin] = 10000;
}

function sendCoin(address receiver, uint256 amount) public returns (bool sufficient) {
if (balances[msg.sender] < amount) return false;
balances[msg.sender] -= amount;
balances[receiver] += amount;
emit Transfer(msg.sender, receiver, amount);
return true;
}

function getBalanceInEth(address addr) public view returns (uint256) {
return getBalance(addr) * 2;
}

function getBalance(address addr) public view returns (uint256) {
return balances[addr];
}
}
Loading
Loading