Skip to content
Open
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
46 changes: 42 additions & 4 deletions e2e/config-default.e2e.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import {test, expect, type Browser} from "@playwright/test";
import {startAnvil, readStubCallCount, type AnvilHandle} from "./fixtures/chain";
import {makeScratchEnv, runCli, readDescriptor, isPidAlive, type ScratchEnv} from "./fixtures/cli";
import {ANVIL_KEY_0, startAnvil, readStubCallCount, type AnvilHandle} from "./fixtures/chain";
import {
installLocalOperator,
makeScratchEnv,
runCli,
readDescriptor,
isPidAlive,
type ScratchEnv,
} from "./fixtures/cli";
import {launchBrowser, establishSession, type BridgeDriver} from "./helpers/bridgePage";

/**
Expand All @@ -11,12 +18,14 @@ import {launchBrowser, establishSession, type BridgeDriver} from "./helpers/brid
*/
const CHAIN_ID = 61343;
const HASH_RE = /0x[0-9a-fA-F]{64}/;
const OPERATOR_PASSWORD = "operator-password";

test.describe.serial("S5 config default walletMode=browser", () => {
let anvil: AnvilHandle;
let browser: Browser;
let driver: BridgeDriver;
let scratch: ScratchEnv;
let operator: `0x${string}`;

test.beforeAll(async () => {
anvil = await startAnvil({chainId: CHAIN_ID});
Expand All @@ -28,6 +37,10 @@ test.describe.serial("S5 config default walletMode=browser", () => {
walletMode: "browser",
timing: {longPollMs: 1000},
});
operator = await installLocalOperator(scratch, {
privateKey: ANVIL_KEY_0,
password: OPERATOR_PASSWORD,
});
({driver} = await establishSession(browser, anvil, scratch));
});

Expand All @@ -46,7 +59,20 @@ test.describe.serial("S5 config default walletMode=browser", () => {

test("bare validator-join signs via session (no --wallet flag)", async () => {
const before = await readStubCallCount(anvil);
const res = await runCli(["staking", "validator-join", "--force", "--amount", "1"], scratch);
const res = await runCli(
[
"staking",
"validator-join",
"--force",
"--amount",
"1",
"--operator",
operator,
"--operator-password",
OPERATOR_PASSWORD,
],
scratch,
);
expect(res.all).toContain("Validator created successfully!");
expect(res.all.match(HASH_RE)?.[0]).toBeTruthy();
expect(await readStubCallCount(anvil)).toBe(before + 1);
Expand All @@ -55,7 +81,19 @@ test.describe.serial("S5 config default walletMode=browser", () => {
test("--wallet keystore overrides config, takes keystore path (no enqueue)", async () => {
const before = await readStubCallCount(anvil);
const res = await runCli(
["staking", "validator-join", "--force", "--amount", "1", "--wallet", "keystore"],
[
"staking",
"validator-join",
"--force",
"--amount",
"1",
"--wallet",
"keystore",
"--operator",
operator,
"--operator-password",
OPERATOR_PASSWORD,
],
scratch,
);
// Keystore path selected: it fails on the missing account rather than
Expand Down
23 changes: 21 additions & 2 deletions e2e/errors.e2e.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {test, expect, type Browser} from "@playwright/test";
import {startAnvil, type AnvilHandle} from "./fixtures/chain";
import {ANVIL_KEY_0, startAnvil, type AnvilHandle} from "./fixtures/chain";
import {
installLocalOperator,
makeScratchEnv,
runCli,
readDescriptor,
Expand All @@ -22,10 +23,12 @@ import {launchBrowser, establishSession, type BridgeDriver} from "./helpers/brid

test.describe.serial("S6a user reject (4001)", () => {
const CHAIN_ID = 61344;
const OPERATOR_PASSWORD = "operator-password";
let anvil: AnvilHandle;
let browser: Browser;
let driver: BridgeDriver;
let scratch: ScratchEnv;
let operator: `0x${string}`;

test.beforeAll(async () => {
anvil = await startAnvil({chainId: CHAIN_ID});
Expand All @@ -36,6 +39,10 @@ test.describe.serial("S6a user reject (4001)", () => {
stubAddress: anvil.stubAddress,
timing: {longPollMs: 1000},
});
operator = await installLocalOperator(scratch, {
privateKey: ANVIL_KEY_0,
password: OPERATOR_PASSWORD,
});
({driver} = await establishSession(browser, anvil, scratch, {behavior: "reject"}));
});

Expand All @@ -54,7 +61,19 @@ test.describe.serial("S6a user reject (4001)", () => {

test("reject surfaces the message, exits non-zero, session survives", async () => {
const res = await runCli(
["staking", "validator-join", "--force", "--amount", "1", "--wallet", "browser"],
[
"staking",
"validator-join",
"--force",
"--amount",
"1",
"--wallet",
"browser",
"--operator",
operator,
"--operator-password",
OPERATOR_PASSWORD,
],
scratch,
);
expect(res.all).toContain("Transaction rejected in wallet");
Expand Down
134 changes: 79 additions & 55 deletions e2e/fixtures/StakingStub.json
Original file line number Diff line number Diff line change
@@ -1,114 +1,138 @@
{
"abi": [
{
"type": "function",
"name": "callCount",
"inputs": [],
"outputs": [
"anonymous": false,
"inputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
"indexed": false,
"internalType": "address",
"name": "operator",
"type": "address"
},
{
"indexed": false,
"internalType": "address",
"name": "validator",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "amount",
"type": "uint256"
}
],
"stateMutability": "view"
"name": "ValidatorJoin",
"type": "event"
},
{
"type": "function",
"name": "lastAmount",
"inputs": [],
"name": "callCount",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256",
"internalType": "uint256"
"type": "uint256"
}
],
"stateMutability": "view"
"stateMutability": "view",
"type": "function"
},
{
"type": "function",
"name": "lastOperator",
"inputs": [],
"inputs": [
{
"internalType": "string",
"name": "_name",
"type": "string"
}
],
"name": "getAddress",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address",
"internalType": "address"
"type": "address"
}
],
"stateMutability": "view"
"stateMutability": "view",
"type": "function"
},
{
"type": "function",
"name": "lastValidator",
"inputs": [],
"name": "getAddressManager",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address",
"internalType": "address"
"type": "address"
}
],
"stateMutability": "view"
"stateMutability": "view",
"type": "function"
},
{
"type": "function",
"name": "validatorJoin",
"inputs": [
"inputs": [],
"name": "lastAmount",
"outputs": [
{
"name": "_operator",
"type": "address",
"internalType": "address"
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "lastOperator",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address",
"internalType": "address"
"type": "address"
}
],
"stateMutability": "payable"
"stateMutability": "view",
"type": "function"
},
{
"type": "function",
"name": "validatorJoin",
"inputs": [],
"name": "lastValidator",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address",
"internalType": "address"
"type": "address"
}
],
"stateMutability": "payable"
"stateMutability": "view",
"type": "function"
},
{
"type": "event",
"name": "ValidatorJoin",
"inputs": [
{
"name": "operator",
"type": "address",
"indexed": false,
"internalType": "address"
"internalType": "uint256[2]",
"name": "_operatorPubKey",
"type": "uint256[2]"
},
{
"name": "validator",
"type": "address",
"indexed": false,
"internalType": "address"
},
"internalType": "bytes",
"name": "",
"type": "bytes"
}
],
"name": "validatorJoin",
"outputs": [
{
"name": "amount",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
"internalType": "address",
"name": "",
"type": "address"
}
],
"anonymous": false
"stateMutability": "payable",
"type": "function"
}
],
"bytecode": "0x6080604052348015600e575f5ffd5b5061050e8061001c5f395ff3fe608060405260043610610054575f3560e01c806301fe0a781461005857806330e7349f1461008857806330ebe468146100b25780634b28f9a2146100d05780636eb3cd49146100fa578063829a86d914610124575b5f5ffd5b610072600480360381019061006d919061032f565b61014e565b60405161007f9190610369565b60405180910390f35b348015610093575f5ffd5b5061009c61015f565b6040516100a99190610369565b60405180910390f35b6100ba610184565b6040516100c79190610369565b60405180910390f35b3480156100db575f5ffd5b506100e4610193565b6040516100f1919061039a565b60405180910390f35b348015610105575f5ffd5b5061010e610198565b60405161011b9190610369565b60405180910390f35b34801561012f575f5ffd5b506101386101bd565b604051610145919061039a565b60405180910390f35b5f610158826101c3565b9050919050565b60025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f61018e336101c3565b905090565b5f5481565b60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60035481565b5f60015f5f8282546101d591906103e0565b92505081905550335f546040516020016101f0929190610478565b604051602081830303815290604052805190602001205f1c90508160015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508060025f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550346003819055507f2b7297b31452d0a13e57c605870ec3c9b4ac6ef33e5cbae7a0f00bc2a3e967828282346040516102c4939291906104a3565b60405180910390a1919050565b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6102fe826102d5565b9050919050565b61030e816102f4565b8114610318575f5ffd5b50565b5f8135905061032981610305565b92915050565b5f60208284031215610344576103436102d1565b5b5f6103518482850161031b565b91505092915050565b610363816102f4565b82525050565b5f60208201905061037c5f83018461035a565b92915050565b5f819050919050565b61039481610382565b82525050565b5f6020820190506103ad5f83018461038b565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6103ea82610382565b91506103f583610382565b925082820190508082111561040d5761040c6103b3565b5b92915050565b5f8160601b9050919050565b5f61042982610413565b9050919050565b5f61043a8261041f565b9050919050565b61045261044d826102f4565b610430565b82525050565b5f819050919050565b61047261046d82610382565b610458565b82525050565b5f6104838285610441565b6014820191506104938284610461565b6020820191508190509392505050565b5f6060820190506104b65f83018661035a565b6104c3602083018561035a565b6104d0604083018461038b565b94935050505056fea26469706673582212202ea3a8dac16f254ee61dc37f81eb395845a459b3af57d33fab7a95c141e032b664736f6c63430008210033"
"bytecode": "0x6080604052348015600e575f5ffd5b506107f48061001c5f395ff3fe60806040526004361061006f575f3560e01c80636eb3cd491161004d5780636eb3cd49146100f1578063829a86d91461011b578063bf40fac114610145578063ea7845f5146101815761006f565b806330e7349f146100735780634b28f9a21461009d5780635492f302146100c7575b5f5ffd5b34801561007e575f5ffd5b506100876101b1565b604051610094919061041c565b60405180910390f35b3480156100a8575f5ffd5b506100b16101d6565b6040516100be919061044d565b60405180910390f35b3480156100d2575f5ffd5b506100db6101db565b6040516100e8919061041c565b60405180910390f35b3480156100fc575f5ffd5b506101056101e2565b604051610112919061041c565b60405180910390f35b348015610126575f5ffd5b5061012f610207565b60405161013c919061044d565b60405180910390f35b348015610150575f5ffd5b5061016b600480360381019061016691906104cf565b61020d565b604051610178919061041c565b60405180910390f35b61019b60048036038101906101969190610590565b61025e565b6040516101a8919061041c565b60405180910390f35b60025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b5f5481565b5f30905090565b60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60035481565b5f7fd6eae5385dae362d454164c313be55f54f548cd511c3559d852e3f3ffe7d65b6838360405161023f929190610629565b60405180910390200361025457309050610258565b5f90505b92915050565b5f5f845f6002811061027357610272610641565b5b60200201358560016002811061028c5761028b610641565b5b60200201356040516020016102a292919061068e565b604051602081830303815290604052805190602001205f1c90506102c5816102cf565b9150509392505050565b5f60015f5f8282546102e191906106e6565b92505081905550335f546040516020016102fc92919061075e565b604051602081830303815290604052805190602001205f1c90508160015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508060025f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550346003819055507f2b7297b31452d0a13e57c605870ec3c9b4ac6ef33e5cbae7a0f00bc2a3e967828282346040516103d093929190610789565b60405180910390a1919050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f610406826103dd565b9050919050565b610416816103fc565b82525050565b5f60208201905061042f5f83018461040d565b92915050565b5f819050919050565b61044781610435565b82525050565b5f6020820190506104605f83018461043e565b92915050565b5f5ffd5b5f5ffd5b5f5ffd5b5f5ffd5b5f5ffd5b5f5f83601f84011261048f5761048e61046e565b5b8235905067ffffffffffffffff8111156104ac576104ab610472565b5b6020830191508360018202830111156104c8576104c7610476565b5b9250929050565b5f5f602083850312156104e5576104e4610466565b5b5f83013567ffffffffffffffff8111156105025761050161046a565b5b61050e8582860161047a565b92509250509250929050565b5f8190508260206002028201111561053557610534610476565b5b92915050565b5f5f83601f8401126105505761054f61046e565b5b8235905067ffffffffffffffff81111561056d5761056c610472565b5b60208301915083600182028301111561058957610588610476565b5b9250929050565b5f5f5f606084860312156105a7576105a6610466565b5b5f6105b48682870161051a565b935050604084013567ffffffffffffffff8111156105d5576105d461046a565b5b6105e18682870161053b565b92509250509250925092565b5f81905092915050565b828183375f83830152505050565b5f61061083856105ed565b935061061d8385846105f7565b82840190509392505050565b5f610635828486610605565b91508190509392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f819050919050565b61068861068382610435565b61066e565b82525050565b5f6106998285610677565b6020820191506106a98284610677565b6020820191508190509392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6106f082610435565b91506106fb83610435565b9250828201905080821115610713576107126106b9565b5b92915050565b5f8160601b9050919050565b5f61072f82610719565b9050919050565b5f61074082610725565b9050919050565b610758610753826103fc565b610736565b82525050565b5f6107698285610747565b6014820191506107798284610677565b6020820191508190509392505050565b5f60608201905061079c5f83018661040d565b6107a9602083018561040d565b6107b6604083018461043e565b94935050505056fea26469706673582212202e7c5c3be52ba719aa8579433c475f973a17163db3866f0a1b1df84a267d892c64736f6c63430008220033"
}
32 changes: 27 additions & 5 deletions e2e/fixtures/StakingStub.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@
pragma solidity ^0.8.13;

/// Minimal recording stub for the Tier-2 browser-wallet e2e harness.
/// Mimics the Staking `validatorJoin` selectors and emits the ValidatorJoin
/// Mimics the proof-bearing Staking `validatorJoin` selector and emits the ValidatorJoin
/// event (address operator, address validator, uint256 amount) the CLI decodes.
/// It also stands in for ConsensusMain, AddressManager, and
/// ValidatorWalletFactory so the SDK can resolve and verify the registration
/// domain before the browser signs the transaction.
/// It stands up NO consensus; it only records the call so the sign->broadcast
/// ->receipt loop can be asserted end to end.
contract StakingStub {
Expand All @@ -14,12 +17,31 @@ contract StakingStub {
address public lastValidator;
uint256 public lastAmount;

function validatorJoin() external payable returns (address) {
return _join(msg.sender);
function getAddressManager() external view returns (address) {
return address(this);
}

function validatorJoin(address _operator) external payable returns (address) {
return _join(_operator);
function getAddress(string calldata _name) external view returns (address) {
if (keccak256(bytes(_name)) == keccak256("ValidatorWalletFactory")) {
return address(this);
}
return address(0);
}

function validatorJoin(
uint256[2] calldata _operatorPubKey,
bytes calldata
) external payable returns (address) {
address operator = address(
uint160(
uint256(
keccak256(
abi.encodePacked(_operatorPubKey[0], _operatorPubKey[1])
)
)
)
);
return _join(operator);
}

function _join(address operator) internal returns (address validator) {
Expand Down
Loading
Loading