Design robust decentralized systems with blockchain technology, smart contracts, and distributed protocols. From DeFi platforms to Web3 applications, we build secure, scalable decentralized architectures.
Custom blockchain development, consensus mechanisms, and distributed ledger design.
Solidity development, contract auditing, and DeFi protocol implementation.
Decentralized application (dApp) architecture with Web3 integration.
Decentralized finance protocols, liquidity pools, and tokenomics design.
Non-fungible token platforms, marketplace design, and metadata management.
Cross-chain bridges, multi-chain architecture, and interoperability protocols.
Secure smart contract development with formal verification and gas optimization
Comprehensive DeFi protocol architecture with tokenomics and governance mechanisms
Optimistic rollups, zk-rollups, and state channels for blockchain scalability and reduced transaction costs.
Multi-chain protocols with atomic swaps, bridge contracts, and interoperability solutions.
Self-sovereign identity systems with verifiable credentials and privacy-preserving authentication.
Distributed storage networks with IPFS, Filecoin, and content-addressed storage systems.
class ProofOfStakeConsensus:
def __init__(self, validators, stake_threshold):
self.validators = validators
self.stake_threshold = stake_threshold
self.current_epoch = 0
self.pending_blocks = []
def select_validator(self):
"""Select validator based on stake-weighted random selection"""
total_stake = sum(v.stake for v in self.validators if v.is_active())
# Weighted random selection
random_value = random.uniform(0, total_stake)
cumulative_stake = 0
for validator in self.validators:
if not validator.is_active():
continue
cumulative_stake += validator.stake
if random_value <= cumulative_stake:
return validator
return None
def validate_block(self, block, validator):
"""Validate block proposal from selected validator"""
# Basic validation
if not self.validate_block_structure(block):
return False, "Invalid block structure"
# Stake validation
if validator.stake < self.stake_threshold:
return False, "Insufficient stake"
# Transaction validation
for tx in block.transactions:
if not self.validate_transaction(tx):
return False, f"Invalid transaction: {tx.hash}"
# Validator signature validation
if not self.verify_signature(block, validator):
return False, "Invalid validator signature"
return True, "Block validated successfully"
def slash_validator(self, validator, offense_type):
"""Slash validator stake for malicious behavior"""
slash_amount = self.calculate_slash_amount(offense_type, validator.stake)
validator.stake -= slash_amount
validator.slashed_amount += slash_amount
# Distribute slashed amount to other validators
remaining_validators = [v for v in self.validators if v != validator and v.is_active()]
reward_per_validator = slash_amount / len(remaining_validators)
for v in remaining_validators:
v.stake += reward_per_validator
# Log slashing event
self.log_slashing_event(validator, offense_type, slash_amount)
import hashlib
import json
from datetime import datetime
class Block:
def __init__(self, transactions, previous_hash, validator_address):
self.timestamp = datetime.utcnow().timestamp()
self.transactions = transactions
self.previous_hash = previous_hash
self.validator_address = validator_address
self.merkle_root = self.calculate_merkle_root()
self.nonce = 0
self.hash = self.calculate_hash()
def calculate_merkle_root(self):
"""Calculate Merkle root of transactions"""
if not self.transactions:
return '0' * 64
# Create list of transaction hashes
tx_hashes = [tx.hash for tx in self.transactions]
# Build Merkle tree
while len(tx_hashes) > 1:
next_level = []
# Process pairs of hashes
for i in range(0, len(tx_hashes), 2):
left = tx_hashes[i]
right = tx_hashes[i + 1] if i + 1 < len(tx_hashes) else tx_hashes[i]
# Combine and hash
combined = left + right
hash_result = hashlib.sha256(combined.encode()).hexdigest()
next_level.append(hash_result)
tx_hashes = next_level
return tx_hashes[0]
def calculate_hash(self):
"""Calculate block hash"""
block_data = {
'timestamp': self.timestamp,
'previous_hash': self.previous_hash,
'merkle_root': self.merkle_root,
'validator_address': self.validator_address,
'nonce': self.nonce
}
block_string = json.dumps(block_data, sort_keys=True)
return hashlib.sha256(block_string.encode()).hexdigest()
class Transaction:
def __init__(self, sender, recipient, amount, private_key):
self.sender = sender
self.recipient = recipient
self.amount = amount
self.timestamp = datetime.utcnow().timestamp()
self.signature = self.sign_transaction(private_key)
self.hash = self.calculate_hash()
def calculate_hash(self):
"""Calculate transaction hash"""
tx_data = {
'sender': self.sender,
'recipient': self.recipient,
'amount': self.amount,
'timestamp': self.timestamp
}
tx_string = json.dumps(tx_data, sort_keys=True)
return hashlib.sha256(tx_string.encode()).hexdigest()
def sign_transaction(self, private_key):
"""Sign transaction with private key"""
# In production, use proper cryptographic signing
# This is a simplified example
message = f"{self.sender}{self.recipient}{self.amount}{self.timestamp}"
signature = hashlib.sha256((message + private_key).encode()).hexdigest()
return signature
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol";
contract TokenVaultV1 is Initializable, OwnableUpgradeable, ReentrancyGuardUpgradeable {
mapping(address => uint256) public balances;
mapping(address => mapping(address => uint256)) public allowances;
uint256 public totalSupply;
string public name;
string public symbol;
uint8 public decimals;
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
event Deposit(address indexed user, uint256 amount);
event Withdrawal(address indexed user, uint256 amount);
function initialize(
string memory _name,
string memory _symbol,
uint8 _decimals,
address _owner
) public initializer {
__Ownable_init();
__ReentrancyGuard_init();
name = _name;
symbol = _symbol;
decimals = _decimals;
_transferOwnership(_owner);
}
function deposit() external payable nonReentrant {
require(msg.value > 0, "Deposit amount must be greater than 0");
balances[msg.sender] += msg.value;
totalSupply += msg.value;
emit Deposit(msg.sender, msg.value);
emit Transfer(address(0), msg.sender, msg.value);
}
function withdraw(uint256 amount) external nonReentrant {
require(amount > 0, "Withdrawal amount must be greater than 0");
require(balances[msg.sender] >= amount, "Insufficient balance");
balances[msg.sender] -= amount;
totalSupply -= amount;
(bool success, ) = payable(msg.sender).call{value: amount}("");
require(success, "Withdrawal failed");
emit Withdrawal(msg.sender, amount);
emit Transfer(msg.sender, address(0), amount);
}
function transfer(address to, uint256 amount) external returns (bool) {
require(to != address(0), "Cannot transfer to zero address");
require(balances[msg.sender] >= amount, "Insufficient balance");
balances[msg.sender] -= amount;
balances[to] += amount;
emit Transfer(msg.sender, to, amount);
return true;
}
function approve(address spender, uint256 amount) external returns (bool) {
allowances[msg.sender][spender] = amount;
emit Approval(msg.sender, spender, amount);
return true;
}
function transferFrom(address from, address to, uint256 amount) external returns (bool) {
require(to != address(0), "Cannot transfer to zero address");
require(balances[from] >= amount, "Insufficient balance");
require(allowances[from][msg.sender] >= amount, "Insufficient allowance");
balances[from] -= amount;
balances[to] += amount;
allowances[from][msg.sender] -= amount;
emit Transfer(from, to, amount);
return true;
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "./TokenVaultV1.sol";
import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
contract VaultFactory {
address public immutable vaultImplementation;
address[] public deployedVaults;
mapping(address => bool) public isVaultDeployed;
event VaultDeployed(
address indexed vault,
address indexed owner,
string name,
string symbol
);
constructor() {
vaultImplementation = address(new TokenVaultV1());
}
function createVault(
string memory name,
string memory symbol,
uint8 decimals
) external returns (address) {
// Deploy proxy contract
bytes memory initData = abi.encodeWithSelector(
TokenVaultV1.initialize.selector,
name,
symbol,
decimals,
msg.sender
);
ERC1967Proxy proxy = new ERC1967Proxy(vaultImplementation, initData);
address vaultAddress = address(proxy);
deployedVaults.push(vaultAddress);
isVaultDeployed[vaultAddress] = true;
emit VaultDeployed(vaultAddress, msg.sender, name, symbol);
return vaultAddress;
}
function getDeployedVaults() external view returns (address[] memory) {
return deployedVaults;
}
function getVaultCount() external view returns (uint256) {
return deployedVaults.length;
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
contract GasOptimizedContract {
// Pack structs to minimize storage slots
struct User {
uint128 balance; // 16 bytes
uint64 lastUpdate; // 8 bytes
uint64 nonce; // 8 bytes
// Total: 32 bytes (1 storage slot)
}
// Use mappings instead of arrays when possible
mapping(address => User) public users;
mapping(bytes32 => bool) public processedHashes;
// Pack multiple boolean values into single storage slot
uint256 private flags; // Use bits for boolean flags
// Constants don't use storage
uint256 public constant MAX_SUPPLY = 1_000_000 * 10**18;
// Immutable variables are stored in bytecode
address public immutable factory;
uint256 public immutable creationTime;
constructor(address _factory) {
factory = _factory;
creationTime = block.timestamp;
}
// Use unchecked arithmetic when safe
function efficientTransfer(address to, uint128 amount) external {
User storage sender = users[msg.sender];
require(sender.balance >= amount, "Insufficient balance");
unchecked {
sender.balance -= amount;
users[to].balance += amount;
sender.nonce++;
}
sender.lastUpdate = uint64(block.timestamp);
// Emit minimal event data
emit Transfer(msg.sender, to, amount);
}
// Batch operations to reduce gas costs
function batchTransfer(
address[] calldata recipients,
uint128[] calldata amounts
) external {
require(recipients.length == amounts.length, "Array length mismatch");
User storage sender = users[msg.sender];
uint128 totalAmount = 0;
// Calculate total first
for (uint256 i = 0; i < amounts.length;) {
totalAmount += amounts[i];
unchecked { ++i; }
}
require(sender.balance >= totalAmount, "Insufficient balance");
unchecked {
sender.balance -= totalAmount;
sender.nonce++;
}
// Execute transfers
for (uint256 i = 0; i < recipients.length;) {
users[recipients[i]].balance += amounts[i];
emit Transfer(msg.sender, recipients[i], amounts[i]);
unchecked { ++i; }
}
sender.lastUpdate = uint64(block.timestamp);
}
// Use bit manipulation for flags
function setFlag(uint8 flagIndex, bool value) external {
if (value) {
flags |= (1 << flagIndex);
} else {
flags &= ~(1 << flagIndex);
}
}
function getFlag(uint8 flagIndex) external view returns (bool) {
return (flags >> flagIndex) & 1 == 1;
}
}
event Transfer(address indexed from, address indexed to, uint256 value);
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
contract LiquidityPool is ERC20, ReentrancyGuard {
IERC20 public immutable token0;
IERC20 public immutable token1;
uint256 public reserve0;
uint256 public reserve1;
uint256 private blockTimestampLast;
// Price oracle variables
uint256 public price0CumulativeLast;
uint256 public price1CumulativeLast;
uint256 private constant MINIMUM_LIQUIDITY = 10**3;
uint256 private constant FEE_DENOMINATOR = 1000;
uint256 private constant FEE_NUMERATOR = 3; // 0.3% fee
event Mint(address indexed sender, uint256 amount0, uint256 amount1);
event Burn(address indexed sender, uint256 amount0, uint256 amount1, address indexed to);
event Swap(
address indexed sender,
uint256 amount0In,
uint256 amount1In,
uint256 amount0Out,
uint256 amount1Out,
address indexed to
);
event Sync(uint256 reserve0, uint256 reserve1);
constructor(address _token0, address _token1) ERC20("LP Token", "LP") {
token0 = IERC20(_token0);
token1 = IERC20(_token1);
}
function addLiquidity(
uint256 amount0Desired,
uint256 amount1Desired,
uint256 amount0Min,
uint256 amount1Min,
address to
) external nonReentrant returns (uint256 amount0, uint256 amount1, uint256 liquidity) {
(amount0, amount1) = _calculateOptimalAmounts(
amount0Desired,
amount1Desired,
amount0Min,
amount1Min
);
require(amount0 >= amount0Min, "Insufficient amount0");
require(amount1 >= amount1Min, "Insufficient amount1");
// Transfer tokens to pool
token0.transferFrom(msg.sender, address(this), amount0);
token1.transferFrom(msg.sender, address(this), amount1);
// Mint LP tokens
liquidity = _mint(to, amount0, amount1);
_update();
emit Mint(msg.sender, amount0, amount1);
}
function removeLiquidity(
uint256 liquidity,
uint256 amount0Min,
uint256 amount1Min,
address to
) external nonReentrant returns (uint256 amount0, uint256 amount1) {
require(liquidity > 0, "Insufficient liquidity");
// Calculate amounts to return
uint256 totalSupply = totalSupply();
amount0 = (liquidity * reserve0) / totalSupply;
amount1 = (liquidity * reserve1) / totalSupply;
require(amount0 >= amount0Min, "Insufficient amount0");
require(amount1 >= amount1Min, "Insufficient amount1");
// Burn LP tokens
_burn(msg.sender, liquidity);
// Transfer tokens to user
token0.transfer(to, amount0);
token1.transfer(to, amount1);
_update();
emit Burn(msg.sender, amount0, amount1, to);
}
function swap(
uint256 amount0Out,
uint256 amount1Out,
address to
) external nonReentrant {
require(amount0Out > 0 || amount1Out > 0, "Insufficient output amount");
require(amount0Out < reserve0 && amount1Out < reserve1, "Insufficient liquidity");
// Transfer output tokens
if (amount0Out > 0) token0.transfer(to, amount0Out);
if (amount1Out > 0) token1.transfer(to, amount1Out);
// Get current balances
uint256 balance0 = token0.balanceOf(address(this));
uint256 balance1 = token1.balanceOf(address(this));
// Calculate input amounts
uint256 amount0In = balance0 > reserve0 - amount0Out ? balance0 - (reserve0 - amount0Out) : 0;
uint256 amount1In = balance1 > reserve1 - amount1Out ? balance1 - (reserve1 - amount1Out) : 0;
require(amount0In > 0 || amount1In > 0, "Insufficient input amount");
// Check constant product formula with fee
uint256 balance0Adjusted = balance0 * FEE_DENOMINATOR - amount0In * FEE_NUMERATOR;
uint256 balance1Adjusted = balance1 * FEE_DENOMINATOR - amount1In * FEE_NUMERATOR;
require(
balance0Adjusted * balance1Adjusted >=
uint256(reserve0) * reserve1 * (FEE_DENOMINATOR**2),
"K"
);
_update();
emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);
}
function _mint(address to, uint256 amount0, uint256 amount1) private returns (uint256 liquidity) {
uint256 totalSupply = totalSupply();
if (totalSupply == 0) {
// First liquidity provider
liquidity = _sqrt(amount0 * amount1) - MINIMUM_LIQUIDITY;
_mint(address(0), MINIMUM_LIQUIDITY); // Lock minimum liquidity
} else {
// Subsequent liquidity providers
liquidity = _min(
(amount0 * totalSupply) / reserve0,
(amount1 * totalSupply) / reserve1
);
}
require(liquidity > 0, "Insufficient liquidity minted");
_mint(to, liquidity);
}
function _update() private {
uint256 blockTimestamp = block.timestamp % 2**32;
uint256 timeElapsed = blockTimestamp - blockTimestampLast;
if (timeElapsed > 0 && reserve0 != 0 && reserve1 != 0) {
// Update price oracles
price0CumulativeLast += uint256(_fraction(reserve1, reserve0)) * timeElapsed;
price1CumulativeLast += uint256(_fraction(reserve0, reserve1)) * timeElapsed;
}
reserve0 = token0.balanceOf(address(this));
reserve1 = token1.balanceOf(address(this));
blockTimestampLast = blockTimestamp;
emit Sync(reserve0, reserve1);
}
// Helper functions
function _sqrt(uint256 y) private pure returns (uint256 z) {
if (y > 3) {
z = y;
uint256 x = y / 2 + 1;
while (x < z) {
z = x;
x = (y / x + x) / 2;
}
} else if (y != 0) {
z = 1;
}
}
function _min(uint256 x, uint256 y) private pure returns (uint256 z) {
z = x < y ? x : y;
}
function _fraction(uint256 numerator, uint256 denominator) private pure returns (uint224) {
return uint224((numerator << 112) / denominator);
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
contract YieldFarm is ReentrancyGuard, Ownable {
struct UserInfo {
uint256 amount; // Staked amount
uint256 rewardDebt; // Reward debt
uint256 pendingRewards; // Pending rewards
uint256 lastStakeTime; // Last stake timestamp
}
struct PoolInfo {
IERC20 stakingToken; // Staking token
IERC20 rewardToken; // Reward token
uint256 allocPoint; // Allocation points
uint256 lastRewardTime; // Last reward distribution time
uint256 accRewardPerShare; // Accumulated rewards per share
uint256 totalStaked; // Total staked amount
uint256 minStakingPeriod; // Minimum staking period
bool isActive; // Pool status
}
PoolInfo[] public poolInfo;
mapping(uint256 => mapping(address => UserInfo)) public userInfo;
uint256 public rewardPerSecond;
uint256 public totalAllocPoint = 0;
uint256 public constant ACC_REWARD_PRECISION = 1e12;
event Deposit(address indexed user, uint256 indexed pid, uint256 amount);
event Withdraw(address indexed user, uint256 indexed pid, uint256 amount);
event EmergencyWithdraw(address indexed user, uint256 indexed pid, uint256 amount);
event Harvest(address indexed user, uint256 indexed pid, uint256 amount);
constructor(uint256 _rewardPerSecond) {
rewardPerSecond = _rewardPerSecond;
}
function addPool(
IERC20 _stakingToken,
IERC20 _rewardToken,
uint256 _allocPoint,
uint256 _minStakingPeriod,
bool _withUpdate
) external onlyOwner {
if (_withUpdate) {
massUpdatePools();
}
uint256 lastRewardTime = block.timestamp;
totalAllocPoint += _allocPoint;
poolInfo.push(PoolInfo({
stakingToken: _stakingToken,
rewardToken: _rewardToken,
allocPoint: _allocPoint,
lastRewardTime: lastRewardTime,
accRewardPerShare: 0,
totalStaked: 0,
minStakingPeriod: _minStakingPeriod,
isActive: true
}));
}
function deposit(uint256 _pid, uint256 _amount) external nonReentrant {
PoolInfo storage pool = poolInfo[_pid];
UserInfo storage user = userInfo[_pid][msg.sender];
require(pool.isActive, "Pool is not active");
require(_amount > 0, "Deposit amount must be greater than 0");
updatePool(_pid);
// Harvest pending rewards
if (user.amount > 0) {
uint256 pending = (user.amount * pool.accRewardPerShare) / ACC_REWARD_PRECISION - user.rewardDebt;
if (pending > 0) {
user.pendingRewards += pending;
}
}
// Transfer staking tokens
pool.stakingToken.transferFrom(msg.sender, address(this), _amount);
// Update user info
user.amount += _amount;
user.lastStakeTime = block.timestamp;
user.rewardDebt = (user.amount * pool.accRewardPerShare) / ACC_REWARD_PRECISION;
// Update pool info
pool.totalStaked += _amount;
emit Deposit(msg.sender, _pid, _amount);
}
function withdraw(uint256 _pid, uint256 _amount) external nonReentrant {
PoolInfo storage pool = poolInfo[_pid];
UserInfo storage user = userInfo[_pid][msg.sender];
require(user.amount >= _amount, "Insufficient staked amount");
require(
block.timestamp >= user.lastStakeTime + pool.minStakingPeriod,
"Minimum staking period not met"
);
updatePool(_pid);
// Harvest pending rewards
uint256 pending = (user.amount * pool.accRewardPerShare) / ACC_REWARD_PRECISION - user.rewardDebt;
if (pending > 0) {
user.pendingRewards += pending;
}
// Update user info
user.amount -= _amount;
user.rewardDebt = (user.amount * pool.accRewardPerShare) / ACC_REWARD_PRECISION;
// Update pool info
pool.totalStaked -= _amount;
// Transfer staking tokens back
pool.stakingToken.transfer(msg.sender, _amount);
emit Withdraw(msg.sender, _pid, _amount);
}
function harvest(uint256 _pid) external nonReentrant {
PoolInfo storage pool = poolInfo[_pid];
UserInfo storage user = userInfo[_pid][msg.sender];
updatePool(_pid);
// Calculate pending rewards
uint256 pending = (user.amount * pool.accRewardPerShare) / ACC_REWARD_PRECISION - user.rewardDebt;
uint256 totalRewards = pending + user.pendingRewards;
if (totalRewards > 0) {
user.pendingRewards = 0;
user.rewardDebt = (user.amount * pool.accRewardPerShare) / ACC_REWARD_PRECISION;
// Transfer reward tokens
safeRewardTransfer(pool.rewardToken, msg.sender, totalRewards);
emit Harvest(msg.sender, _pid, totalRewards);
}
}
function updatePool(uint256 _pid) public {
PoolInfo storage pool = poolInfo[_pid];
if (block.timestamp <= pool.lastRewardTime) {
return;
}
if (pool.totalStaked == 0 || pool.allocPoint == 0) {
pool.lastRewardTime = block.timestamp;
return;
}
uint256 timeElapsed = block.timestamp - pool.lastRewardTime;
uint256 reward = (timeElapsed * rewardPerSecond * pool.allocPoint) / totalAllocPoint;
pool.accRewardPerShare += (reward * ACC_REWARD_PRECISION) / pool.totalStaked;
pool.lastRewardTime = block.timestamp;
}
function massUpdatePools() public {
uint256 length = poolInfo.length;
for (uint256 pid = 0; pid < length; ++pid) {
updatePool(pid);
}
}
function pendingReward(uint256 _pid, address _user) external view returns (uint256) {
PoolInfo storage pool = poolInfo[_pid];
UserInfo storage user = userInfo[_pid][_user];
uint256 accRewardPerShare = pool.accRewardPerShare;
if (block.timestamp > pool.lastRewardTime && pool.totalStaked != 0) {
uint256 timeElapsed = block.timestamp - pool.lastRewardTime;
uint256 reward = (timeElapsed * rewardPerSecond * pool.allocPoint) / totalAllocPoint;
accRewardPerShare += (reward * ACC_REWARD_PRECISION) / pool.totalStaked;
}
return (user.amount * accRewardPerShare) / ACC_REWARD_PRECISION - user.rewardDebt + user.pendingRewards;
}
function safeRewardTransfer(IERC20 _rewardToken, address _to, uint256 _amount) internal {
uint256 rewardBalance = _rewardToken.balanceOf(address(this));
if (_amount > rewardBalance) {
_rewardToken.transfer(_to, rewardBalance);
} else {
_rewardToken.transfer(_to, _amount);
}
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
contract CrossChainBridge is ReentrancyGuard, AccessControl {
bytes32 public constant VALIDATOR_ROLE = keccak256("VALIDATOR_ROLE");
bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE");
struct BridgeTransaction {
address sender;
address recipient;
uint256 amount;
uint256 sourceChainId;
uint256 targetChainId;
address tokenAddress;
bytes32 txHash;
uint256 blockNumber;
bool processed;
uint256 validatorCount;
mapping(address => bool) validatorSignatures;
}
struct ChainInfo {
uint256 chainId;
string name;
bool isActive;
uint256 minConfirmations;
uint256 bridgeFee; // In basis points
}
mapping(bytes32 => BridgeTransaction) public bridgeTransactions;
mapping(uint256 => ChainInfo) public supportedChains;
mapping(address => mapping(uint256 => bool)) public supportedTokens;
uint256 public constant REQUIRED_VALIDATOR_SIGNATURES = 3;
uint256 public constant MAX_VALIDATORS = 7;
uint256 public validatorCount;
event BridgeInitiated(
bytes32 indexed txId,
address indexed sender,
address indexed recipient,
uint256 amount,
uint256 sourceChainId,
uint256 targetChainId,
address tokenAddress
);
event BridgeCompleted(
bytes32 indexed txId,
address indexed recipient,
uint256 amount
);
event ValidatorSignatureAdded(
bytes32 indexed txId,
address indexed validator
);
constructor() {
_grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
_grantRole(ADMIN_ROLE, msg.sender);
}
function initiateBridge(
address recipient,
uint256 amount,
uint256 targetChainId,
address tokenAddress
) external payable nonReentrant {
require(supportedChains[targetChainId].isActive, "Target chain not supported");
require(supportedTokens[tokenAddress][targetChainId], "Token not supported on target chain");
require(amount > 0, "Amount must be greater than 0");
// Calculate bridge fee
uint256 bridgeFee = (amount * supportedChains[targetChainId].bridgeFee) / 10000;
require(msg.value >= bridgeFee, "Insufficient bridge fee");
// Lock tokens on source chain
IERC20(tokenAddress).transferFrom(msg.sender, address(this), amount);
// Create bridge transaction ID
bytes32 txId = keccak256(
abi.encodePacked(
msg.sender,
recipient,
amount,
block.chainid,
targetChainId,
tokenAddress,
block.timestamp
)
);
// Store bridge transaction
BridgeTransaction storage bridgeTx = bridgeTransactions[txId];
bridgeTx.sender = msg.sender;
bridgeTx.recipient = recipient;
bridgeTx.amount = amount;
bridgeTx.sourceChainId = block.chainid;
bridgeTx.targetChainId = targetChainId;
bridgeTx.tokenAddress = tokenAddress;
bridgeTx.txHash = keccak256(abi.encodePacked(block.number, tx.origin));
bridgeTx.blockNumber = block.number;
bridgeTx.processed = false;
bridgeTx.validatorCount = 0;
emit BridgeInitiated(
txId,
msg.sender,
recipient,
amount,
block.chainid,
targetChainId,
tokenAddress
);
}
function validateBridgeTransaction(
bytes32 txId,
bytes memory signature
) external onlyRole(VALIDATOR_ROLE) {
BridgeTransaction storage bridgeTx = bridgeTransactions[txId];
require(!bridgeTx.processed, "Transaction already processed");
require(!bridgeTx.validatorSignatures[msg.sender], "Already signed by validator");
// Verify signature
bytes32 messageHash = keccak256(
abi.encodePacked(
bridgeTx.sender,
bridgeTx.recipient,
bridgeTx.amount,
bridgeTx.sourceChainId,
bridgeTx.targetChainId,
bridgeTx.tokenAddress
)
);
address signer = recoverSigner(messageHash, signature);
require(signer == msg.sender, "Invalid signature");
// Add validator signature
bridgeTx.validatorSignatures[msg.sender] = true;
bridgeTx.validatorCount++;
emit ValidatorSignatureAdded(txId, msg.sender);
// Execute bridge if enough validators signed
if (bridgeTx.validatorCount >= REQUIRED_VALIDATOR_SIGNATURES) {
_executeBridge(txId);
}
}
function _executeBridge(bytes32 txId) private {
BridgeTransaction storage bridgeTx = bridgeTransactions[txId];
require(!bridgeTx.processed, "Transaction already processed");
// Mark as processed
bridgeTx.processed = true;
// Mint or unlock tokens on target chain
if (bridgeTx.targetChainId == block.chainid) {
// This is the target chain - mint/unlock tokens
IERC20(bridgeTx.tokenAddress).transfer(bridgeTx.recipient, bridgeTx.amount);
emit BridgeCompleted(txId, bridgeTx.recipient, bridgeTx.amount);
}
}
function addSupportedChain(
uint256 chainId,
string memory name,
uint256 minConfirmations,
uint256 bridgeFee
) external onlyRole(ADMIN_ROLE) {
supportedChains[chainId] = ChainInfo({
chainId: chainId,
name: name,
isActive: true,
minConfirmations: minConfirmations,
bridgeFee: bridgeFee
});
}
function addSupportedToken(
address tokenAddress,
uint256[] memory chainIds
) external onlyRole(ADMIN_ROLE) {
for (uint256 i = 0; i < chainIds.length; i++) {
supportedTokens[tokenAddress][chainIds[i]] = true;
}
}
function addValidator(address validator) external onlyRole(ADMIN_ROLE) {
require(validatorCount < MAX_VALIDATORS, "Maximum validators reached");
require(!hasRole(VALIDATOR_ROLE, validator), "Already a validator");
_grantRole(VALIDATOR_ROLE, validator);
validatorCount++;
}
function removeValidator(address validator) external onlyRole(ADMIN_ROLE) {
require(hasRole(VALIDATOR_ROLE, validator), "Not a validator");
require(validatorCount > REQUIRED_VALIDATOR_SIGNATURES, "Cannot remove validator");
_revokeRole(VALIDATOR_ROLE, validator);
validatorCount--;
}
function recoverSigner(bytes32 messageHash, bytes memory signature) private pure returns (address) {
bytes32 ethSignedMessageHash = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", messageHash));
(bytes32 r, bytes32 s, uint8 v) = splitSignature(signature);
return ecrecover(ethSignedMessageHash, v, r, s);
}
function splitSignature(bytes memory sig) private pure returns (bytes32 r, bytes32 s, uint8 v) {
require(sig.length == 65, "Invalid signature length");
assembly {
r := mload(add(sig, 32))
s := mload(add(sig, 64))
v := byte(0, mload(add(sig, 96)))
}
}
}
class StateChannel:
def __init__(self, participants, initial_state, challenge_period=7*24*3600):
self.participants = participants
self.state = initial_state
self.sequence_number = 0
self.challenge_period = challenge_period
self.is_closed = False
self.latest_state_hash = self.hash_state(initial_state)
self.pending_challenges = {}
def update_state(self, new_state, signatures):
"""Update channel state with new signed state"""
if self.is_closed:
raise Exception("Channel is closed")
# Verify signatures from all participants
state_hash = self.hash_state(new_state)
message = f"{state_hash}:{self.sequence_number + 1}"
for i, participant in enumerate(self.participants):
if not self.verify_signature(message, signatures[i], participant):
raise Exception(f"Invalid signature from participant {participant}")
# Update state
self.state = new_state
self.sequence_number += 1
self.latest_state_hash = state_hash
return True
def initiate_challenge(self, challenger, disputed_state, proof):
"""Initiate fraud proof challenge"""
if self.is_closed:
raise Exception("Channel is closed")
challenge_id = f"{challenger}:{time.time()}"
challenge_deadline = time.time() + self.challenge_period
self.pending_challenges[challenge_id] = {
'challenger': challenger,
'disputed_state': disputed_state,
'proof': proof,
'deadline': challenge_deadline,
'resolved': False
}
return challenge_id
def resolve_challenge(self, challenge_id, resolution_proof):
"""Resolve fraud proof challenge"""
if challenge_id not in self.pending_challenges:
raise Exception("Challenge not found")
challenge = self.pending_challenges[challenge_id]
if challenge['resolved']:
raise Exception("Challenge already resolved")
if time.time() > challenge['deadline']:
# Challenge period expired, accept disputed state
self.state = challenge['disputed_state']
challenge['resolved'] = True
return "Challenge accepted - state reverted"
# Verify resolution proof
if self.verify_fraud_proof(challenge['proof'], resolution_proof):
challenge['resolved'] = True
return "Challenge rejected - current state maintained"
else:
# Invalid proof, accept challenge
self.state = challenge['disputed_state']
challenge['resolved'] = True
return "Challenge accepted - state reverted"
def close_channel(self, final_signatures):
"""Close channel and settle on-chain"""
if self.is_closed:
raise Exception("Channel already closed")
# Verify all challenges are resolved
for challenge in self.pending_challenges.values():
if not challenge['resolved'] and time.time() <= challenge['deadline']:
raise Exception("Pending challenges must be resolved")
# Verify final state signatures
message = f"{self.latest_state_hash}:{self.sequence_number}:FINAL"
for i, participant in enumerate(self.participants):
if not self.verify_signature(message, final_signatures[i], participant):
raise Exception(f"Invalid final signature from participant {participant}")
# Execute final state settlement
self.settle_on_chain(self.state)
self.is_closed = True
return self.state
def hash_state(self, state):
"""Hash state for integrity verification"""
state_string = json.dumps(state, sort_keys=True)
return hashlib.sha256(state_string.encode()).hexdigest()
def verify_signature(self, message, signature, public_key):
"""Verify digital signature"""
# Simplified signature verification
# In production, use proper cryptographic libraries
message_hash = hashlib.sha256(message.encode()).hexdigest()
expected_signature = hashlib.sha256((message_hash + public_key).encode()).hexdigest()
return signature == expected_signature
def verify_fraud_proof(self, challenge_proof, resolution_proof):
"""Verify fraud proof validity"""
# Simplified fraud proof verification
# In production, implement proper state transition verification
return resolution_proof['valid'] and resolution_proof['state_transition_hash'] == challenge_proof['disputed_hash']
def settle_on_chain(self, final_state):
"""Settle final state on main chain"""
# This would interact with main chain smart contract
print(f"Settling final state on-chain: {final_state}")