A modular and extensible transaction execution system built to power scalable smart interactions in the Web3 ecosystem. STXN v2 leverages off-chain computation, DAG-based execution, and a solver marketplace for cost-efficient, user-friendly, and interoperable infrastructure.
STXN provides a hybrid infrastructure to allow seamless execution of user-defined operations (CallObjects) through off-chain solvers and smart contract execution layers. The system focuses on:
- Cost reduction through off-chain computation and optimized execution
- Frictionless user onboarding with gasless objective submission
- Smart account compatibility with EIP-7702 support
- Off-chain composability through modular architecture
- Secure execution with comprehensive verification mechanisms
- DAG-based execution: Supports complex call dependencies and parallel execution
- Return value verification: Ensures execution integrity through return value validation
- Gas optimization: Efficient storage patterns and execution ordering
- Solver marketplace: Decentralized execution through competitive solvers
- Portal system: Controlled execution environment with approval mechanisms
- UserObjective submission: Gasless objective submission with tip-based incentives
- CallObject structure: Comprehensive call definition with verification flags
- Additional data support: Extensible metadata for complex operations
- Multi-chain support: Chain-specific execution with proper validation
- Comprehensive test suite: Unit tests, integration tests, and end-to-end scenarios
- Mock contracts: ERC20 tokens, flash loans, and DeFi protocols for testing
- Time-based utilities: BlockTime and scheduling mechanisms
- KITN token system: Custom token for testing and incentives
- Multi-network support: Mainnet, testnet, and Lestnet deployment
- Automated deployment: Script-based deployment with parameter validation
- Contract verification: Automated verification on multiple block explorers
- Salt-based deployment: Deterministic deployment for upgradeable contracts
src/
βββ CallBreaker.sol # Main execution contract
βββ interfaces/ # System interfaces
β βββ ICallBreaker.sol # Core execution interface
β βββ ISmartExecute.sol # Smart execution interface
β βββ IApprover.sol # Approval mechanism interface
β βββ IMultiCall3.sol # Multi-call interface
βββ tests/ # Test contracts and utilities
β βββ BlockTime.sol # Time-based utilities
β βββ KITNToken.sol # Custom token implementation
β βββ Defi/ # DeFi protocol mocks
β βββ interfaces/ # Test-specific interfaces
βββ utils/ # Utility contracts and libraries
β βββ MultiCall3.sol # Multi-call implementation
β βββ MockERC20Token.sol # Mock ERC20 for testing
β βββ interfaces/ # Utility interfaces
βββ mock/ # Mock contracts
βββ MockERC20.sol # Basic ERC20 mock
test/ # Foundry test files
βββ CallBreaker.t.sol # Main contract tests
βββ e2e/ # End-to-end test scenarios
βββ utils/ # Test utilities
script/ # Deployment scripts
βββ DeployCallBreaker.s.sol # CallBreaker deployment
βββ DeployMockERC20.s.sol # Mock token deployment
βββ utilities/ # Deployment utilities
lib/ # Foundry dependencies
βββ forge-std/ # Foundry standard library
βββ openzeppelin-contracts-upgradeable/ # OpenZeppelin contracts
βββ openzeppelin-foundry-upgrades/ # Foundry upgrade utilities
- Foundry β Smart contract development and testing framework
- Solidity 0.8.30 β Smart contract programming language
- OpenZeppelin β Secure smart contract libraries
- EIP-712 β Structured data signing standard
- EIP-7702 β Smart account delegation (planned)
# Install Foundry
curl -L https://foundry.paradigm.xyz | bash
foundryup
# Clone Repository
git clone git@github.com:smart-transaction/stxn-smart-contracts-v2.git
cd stxn-smart-contracts-v2
# Install Dependencies
forge install
# Build Contracts
forge build
# Run Tests
forge test
# Run Specific Test
forge test --match-test testExecuteAndVerifyWithUserReturns -vvvThe simplest way to use STXN is to submit a single call objective:
// 1. Create a CallObject
CallObject memory callObj = CallObject({
salt: 1,
amount: 0,
gas: 100000,
addr: targetContract,
callvalue: abi.encodeWithSignature("functionName(uint256)", 123),
returnvalue: "", // Empty for solver-provided returns
skippable: false,
verifiable: true,
exposeReturn: false
});
// 2. Create UserObjective
CallObject[] memory callObjs = new CallObject[](1);
callObjs[0] = callObj;
UserObjective memory userObjective = UserObjective({
appId: hex"01",
nonce: 1,
tip: 0.1 ether,
chainId: block.chainid,
maxFeePerGas: 20 gwei,
maxPriorityFeePerGas: 2 gwei,
sender: msg.sender,
signature: signature, // EIP-712 signature
callObjects: callObjs
});
// 3. Submit objective
callBreaker.pushUserObjective(userObjective, new AdditionalData[](0));Execute multiple calls with dependencies:
// Create multiple call objects
CallObject[] memory callObjs = new CallObject[](3);
// Call 1: Approve tokens
callObjs[0] = CallObject({
salt: 1,
amount: 0,
gas: 100000,
addr: tokenContract,
callvalue: abi.encodeWithSignature("approve(address,uint256)", spender, amount),
returnvalue: abi.encode(true),
skippable: false,
verifiable: true,
exposeReturn: false
});
// Call 2: Swap tokens (depends on approval)
callObjs[1] = CallObject({
salt: 2,
amount: 0,
gas: 200000,
addr: swapContract,
callvalue: abi.encodeWithSignature("swap(uint256)", amount),
returnvalue: "",
skippable: false,
verifiable: true,
exposeReturn: true // Expose return for other calls
});
// Call 3: Transfer result (depends on swap)
callObjs[2] = CallObject({
salt: 3,
amount: 0,
gas: 100000,
addr: tokenContract,
callvalue: abi.encodeWithSignature("transfer(address,uint256)", recipient, 0), // Amount from previous call
returnvalue: abi.encode(true),
skippable: false,
verifiable: true,
exposeReturn: false
});Complete flash loan arbitrage scenario:
function executeFlashLoanArbitrage() external {
// User submits swap objective
CallObject[] memory userCallObjs = new CallObject[](2);
// Approve tokens for swap
userCallObjs[0] = CallObject({
salt: 1,
amount: 0,
gas: 100000,
addr: daiToken,
callvalue: abi.encodeWithSignature("approve(address,uint256)", pool, 10e18),
returnvalue: abi.encode(true),
skippable: false,
verifiable: true,
exposeReturn: false
});
// Execute swap
userCallObjs[1] = CallObject({
salt: 2,
amount: 0,
gas: 200000,
addr: pool,
callvalue: abi.encodeWithSignature("swapDAIForWETH(uint256,uint256)", 10, 2),
returnvalue: "",
skippable: false,
verifiable: true,
exposeReturn: false
});
// Solver provides liquidity and executes
CallObject[] memory solverCallObjs = new CallObject[](7);
// 1. Approve tokens for liquidity provision
solverCallObjs[0] = CallObject({
salt: 0,
amount: 0,
gas: 100000,
addr: daiToken,
callvalue: abi.encodeWithSignature("approve(address,uint256)", pool, 100e18),
returnvalue: abi.encode(true),
skippable: false,
verifiable: true,
exposeReturn: false
});
// 2. Provide liquidity
solverCallObjs[1] = CallObject({
salt: 1,
amount: 0,
gas: 200000,
addr: pool,
callvalue: abi.encodeWithSignature("provideLiquidity(address,uint256,uint256)", address(callBreaker), 100, 10),
returnvalue: "",
skippable: false,
verifiable: true,
exposeReturn: false
});
// 3. Check slippage (future call)
solverCallObjs[2] = CallObject({
salt: 2,
amount: 0,
gas: 100000,
addr: pool,
callvalue: abi.encodeWithSignature("checkSlippage(uint256)", 2),
returnvalue: "",
skippable: false,
verifiable: true,
exposeReturn: true // Expose for verification
});
// 4-7. Withdraw liquidity and cleanup...
// Execute with custom order
uint256[] memory orderOfExecution = new uint256[](9);
orderOfExecution[0] = 2; // Provide liquidity first
orderOfExecution[1] = 3; // Check slippage
orderOfExecution[2] = 4; // User approval
orderOfExecution[3] = 5; // User swap
orderOfExecution[4] = 6; // Withdraw liquidity
// ... rest of execution order
callBreaker.executeAndVerify(
userObjs,
returnValues,
orderOfExecution,
mevTimeData
);
}Submit objectives for different chains:
// Solana chain objective
UserObjective memory solanaObjective = UserObjective({
appId: hex"01",
nonce: 1,
tip: 0.1 ether,
chainId: 101, // Solana chain ID
maxFeePerGas: 0,
maxPriorityFeePerGas: 0,
sender: msg.sender,
signature: signature,
callObjects: callObjs
});
// Add additional data for cross-chain context
AdditionalData[] memory additionalData = new AdditionalData[](3);
additionalData[0] = AdditionalData({
key: keccak256(abi.encode("amount")),
value: abi.encode(10e18)
});
additionalData[1] = AdditionalData({
key: keccak256(abi.encode("SolanaContractAddress")),
value: abi.encode(keccak256(abi.encode("0x1")))
});
additionalData[2] = AdditionalData({
key: keccak256(abi.encode("SolanaWalletAddress")),
value: abi.encode(keccak256(abi.encode("0x2")))
});
callBreaker.pushUserObjective(solanaObjective, additionalData);STXN operates on a user-solver model:
- Users submit objectives (CallObjects) with signatures
- Solvers execute objectives in optimal order with DAG dependencies
- CallBreaker verifies execution and manages state
# 1. Clone and setup
git clone git@github.com:smart-transaction/stxn-smart-contracts-v2.git
cd stxn-smart-contracts-v2
forge install
# 2. Create your test file
touch test/MyIntegration.t.sol
# 3. Import required contracts
import "forge-std/Test.sol";
import {CallBreaker} from "src/CallBreaker.sol";
import {CallObject, UserObjective} from "src/interfaces/ICallBreaker.sol";contract MyIntegrationTest is Test {
CallBreaker public callBreaker;
address public user = vm.addr(0x1);
address public solver = vm.addr(0x2);
function setUp() public {
callBreaker = new CallBreaker(address(this));
// Fund user and solver
vm.deal(user, 10 ether);
vm.deal(solver, 10 ether);
// Deposit to CallBreaker
vm.prank(user);
callBreaker.deposit{value: 5 ether}();
}
function testBasicExecution() public {
// Your test implementation here
}
}// Generate EIP-712 signature
function generateSignature(
uint256 nonce,
address sender,
uint256 signerKey,
CallObject[] memory callObjects
) internal view returns (bytes memory) {
bytes32 messageHash = callBreaker.getMessageHash(
abi.encode(nonce, sender, abi.encode(callObjects))
);
(uint8 v, bytes32 r, bytes32 s) = vm.sign(signerKey, messageHash);
return abi.encodePacked(r, s, v);
}// Set approval addresses for specific app IDs
callBreaker.setApprovalAddresses(
appId,
preApprovalContract,
postApprovalContract
);// Add MEV time data for execution
AdditionalData[] memory mevTimeData = new AdditionalData[](1);
mevTimeData[0] = AdditionalData({
key: keccak256(abi.encodePacked("swapPartner")),
value: abi.encode(partnerAddress)
});
MevTimeData memory mevData = MevTimeData({
validatorSignature: validatorSignature,
mevTimeDataValues: mevTimeData
});- Use helper libraries from
test/utils/ - Test edge cases like insufficient balance, invalid signatures
- Verify return values match expectations
- Test execution order dependencies
- Use proper gas limits for different call types
# Deploy to testnet
./deploy.sh TESTNET CallBreaker
# Deploy with custom salt
./deploy.sh TESTNET CallBreaker 12345
# Deploy multiple mock tokens
./deploy.sh TESTNET MockERC20 2 '["TokenA","TokenB"]' '["TA","TB"]'The project includes a comprehensive deployment script that supports multiple networks and contract types:
./deploy.sh <NETWORK_TYPE> <CONTRACT_NAME> [chains] [count] [names-array] [symbols-array]<NETWORK_TYPE>: Target network (MAINNET,TESTNET,LESTNET)<CONTRACT_NAME>: Contract to deploy (CallBreaker,MockERC20, etc.)[chains]: Optional JSON array of target chains[count]: Number of instances to deploy (for MockERC20)[names-array]: JSON array of token names (for MockERC20)[symbols-array]: JSON array of token symbols (for MockERC20)
Deploy CallBreaker:
# Basic deployment
./deploy.sh TESTNET CallBreaker
# With custom salt
./deploy.sh TESTNET CallBreaker 12345
# To specific chains
./deploy.sh TESTNET CallBreaker '["ethereum", "polygon"]'Deploy MockERC20 tokens:
# Single token
./deploy.sh TESTNET MockERC20 1 '["TestToken"]' '["TEST"]'
# Multiple tokens
./deploy.sh TESTNET MockERC20 2 '["TokenA","TokenB"]' '["TA","TB"]'Deploy to Lestnet:
./deploy.sh LESTNET CallBreakerforge verify-contract \
--rpc-url https://service.lestnet.org \
<CONTRACT_ADDRESS> \
<CONTRACT_NAME> \
--verifier blockscout \
--verifier-url https://explore.lestnet.org/api/forge verify-contract \
<CONTRACT_ADDRESS> \
<CONTRACT_PATH>:<CONTRACT_NAME> \
--chain <CHAIN_ID> \
--watch \
--etherscan-api-key <API_KEY>Example:
forge verify-contract \
0x1234...5678 \
src/CallBreaker.sol:CallBreaker \
--chain 1 \
--watch \
--etherscan-api-key YOUR_API_KEYCreate a .env file for deployment configuration:
# .env
PRIVATE_KEY=your_private_key
ETHERSCAN_API_KEY=your_etherscan_api_key
LESTNET_RPC_URL=https://service.lestnet.orgThe deployment script uses config/networks.json for network-specific settings. Supported networks:
- MAINNET: Ethereum mainnet
- TESTNET: Ethereum testnets (Sepolia, Goerli)
- LESTNET: Lestnet blockchain
# Run all tests
forge test
# Run with verbose output
forge test -vvv
# Run specific test
forge test --match-test testExecuteAndVerifyWithUserReturns
# Run tests with gas reporting
forge test --gas-report
# Run tests in parallel
forge test --paralleltest/
βββ CallBreaker.t.sol # Main contract tests
βββ e2e/ # End-to-end scenarios
β βββ SelfCheckout.t.sol # DeFi self-checkout example
β βββ FlashLiquiditySwap.t.sol # Flash loan arbitrage
β βββ KITNDisbursement.t.sol # Token disbursement
β βββ MEVTimeCompute.t.sol # MEV protection
β βββ BlockTimeScheduler.t.sol # Time-based scheduling
βββ utils/ # Test utilities
βββ CallBreakerTestHelper.sol # Helper functions
βββ SignatureHelper.sol # Signature generation
- Unit Tests: Individual function testing
- Integration Tests: Multi-contract interactions
- E2E Tests: Complete user scenarios
- Edge Case Tests: Error conditions and limits
Use the provided helper libraries for consistent test setup:
import {CallBreakerTestHelper} from "test/utils/CallBreakerTestHelper.sol";
import {SignatureHelper} from "test/utils/SignatureHelper.sol";
contract MyTest is Test {
function testMyScenario() public {
// Use helpers for consistent setup
CallObject[] memory callObjs = new CallObject[](1);
callObjs[0] = CallBreakerTestHelper.buildCallObject(
targetContract,
callData,
expectedReturn
);
// Generate signature
bytes memory signature = signatureHelper.generateSignature(
nonce, sender, privateKey, callObjs
);
// Build user objective
UserObjective memory objective = CallBreakerTestHelper.buildUserObjective(
nonce, sender, signature, callObjs
);
// Test execution
callBreaker.pushUserObjective(objective, new AdditionalData[](0));
}
}The CallBreaker contract uses several gas optimization techniques:
- Transient storage for execution state
- Efficient storage patterns with packed structs
- Batch operations for multiple calls
- Return value caching to avoid redundant calls
- Signature Verification: All objectives must be properly signed
- Balance Checks: Sufficient ETH balance required for execution
- Gas Limits: Proper gas limits prevent out-of-gas failures
- Return Value Verification: Ensures execution integrity
- Access Control: Owner-only functions for critical operations
// Optimize gas usage
CallObject memory callObj = CallObject({
salt: 1,
amount: 0,
gas: 100000, // Set appropriate gas limit
addr: targetContract,
callvalue: callData,
returnvalue: expectedReturn,
skippable: false,
verifiable: true,
exposeReturn: false // Set to true only if needed
});We welcome contributions! Please follow these steps:
- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-feature - Write tests for your changes
- Run the test suite:
forge test - Commit your changes:
git commit -m 'Add amazing feature' - Push to the branch:
git push origin feature/amazing-feature - Open a Pull Request
- Follow Solidity style guidelines
- Add comprehensive tests for new features
- Update documentation for API changes
- Ensure all tests pass before submitting PR
- Use meaningful commit messages
// Use descriptive variable names
address public immutable callBreakerAddress;
// Add comprehensive documentation
/// @notice Executes and verifies call objects
/// @param userObjectives Array of user objectives to execute
/// @param returnValues Expected return values for verification
/// @param orderOfExecution Order of execution for DAG optimization
function executeAndVerify(
UserObjective[] calldata userObjectives,
bytes[] calldata returnValues,
uint256[] calldata orderOfExecution,
MevTimeData calldata mevTimeData
) external;- Foundry Book - Foundry documentation
- OpenZeppelin Contracts - Security patterns
- EIP-712 - Structured data signing
- GitHub Issues - Bug reports and feature requests
- Discussions - Community discussions
- Audit Status: In progress
- Bug Bounty: Contact team for details
- Security Contact: security@smart-transaction.com
This project is licensed under the Business Source License 1.1 - see the LICENSE file for details.
Business Source License 1.1 Β© Smart Transaction Corp.
- Website: smart-transaction.com
- Email: contact@smart-transaction.com
- GitHub: smart-transaction/stxn-smart-contracts-v2
- Issues: GitHub Issues
- Foundry - Smart contract development framework
- OpenZeppelin - Secure smart contract libraries
- Ethereum Foundation - Blockchain infrastructure