Overview
S Balance
S Value
$0.00More Info
Private Name Tags
ContractCreator
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
EmoliumBridgeDeposit
Compiler Version
v0.8.26+commit.8a97fa7a
Optimization Enabled:
No with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./sources/IMintableERC20.sol"; import "./sources/OZ/IERC20.sol"; import "./sources/OZ/ReentrancyGuard.sol"; import "./sources/OZ/ERC20Burnable.sol"; import "./sources/OZ/Ownable.sol"; import "./chiefValidator.sol"; import "./sources/IWETH.sol"; import "./chainRouter.sol"; contract EmoliumBridgeDeposit is ReentrancyGuard, Ownable { ChiefValidator public chiefValidator; IWETH public weth; ChainRouter public chainRouter; uint256 defaultNetworkId = 1; // Store Deposit Proofs mapping(bytes32 => bool) public depositProofs; // Event to generate proof event DepositProofGenerated(address indexed depositor, bytes32 proofHash, string proofData); // Event for ERC20 or WETH deposit event ERC20Deposited(address indexed user, address indexed token, uint256 amount); event ETHDeposited(address indexed user, uint256 amount); event ERC20Bridged(address indexed token, uint256 amount); constructor(address payable _chiefValidator, address _initialOwner, address _weth, address _chainRouter) Ownable(_initialOwner) { chiefValidator = ChiefValidator(_chiefValidator); weth = IWETH(_weth); chainRouter = ChainRouter(_chainRouter); transferOwnership(_initialOwner); } // Deposit ETH and generate proof function depositETH(string memory chainDestination, uint256 networkId) external payable nonReentrant { require(msg.value > 0, "Must send ETH"); require(chainRouter.isChainRegistered(networkId), "Destination chain not registered"); weth.deposit{value: msg.value}(); uint256 amount = msg.value; require(weth.transfer(address(chiefValidator), amount), "Transfer to ChiefValidator failed"); string memory proofData = _generateProofData(msg.sender, address(weth), amount, chainDestination); bytes32 proofHash = keccak256(abi.encodePacked(proofData)); depositProofs[proofHash] = true; emit ETHDeposited(msg.sender, amount); emit DepositProofGenerated(msg.sender, proofHash, proofData); } // Deposit ERC20 and generate proof function depositERC20(address token, uint256 amount, string memory chainDestination, uint256 networkId) external nonReentrant { require(amount > 0, "Amount must be greater than 0"); require(chainRouter.isChainRegistered(networkId), "Destination chain not registered"); require(IERC20(token).transferFrom(msg.sender, address(this), amount), "Transfer failed"); string memory proofData = _generateProofData(msg.sender, token, amount, chainDestination); bytes32 proofHash = keccak256(abi.encodePacked(proofData)); depositProofs[proofHash] = true; if (chiefValidator.isBridgeTokenRegistered(token)) { _burnERC20(token, amount); } else { require(IERC20(token).transfer(address(chiefValidator), amount), "Transfer to ChiefValidator failed"); emit ERC20Deposited(msg.sender, token, amount); } emit DepositProofGenerated(msg.sender, proofHash, proofData); } // Function to burn ERC20 tokens function _burnERC20(address token, uint256 amount) internal { ERC20Burnable burnableToken = ERC20Burnable(token); burnableToken.burn(amount); emit ERC20Bridged(token, amount); } // Generate a string with the deposit information function _generateProofData(address depositor, address token, uint256 amount, string memory chainDestination) internal view returns (string memory) { return string(abi.encodePacked( toAsciiString(depositor), ",", toAsciiString(token), ",", uint2str(amount), ",", uint2str(block.timestamp), ",", chainDestination )); } // Function to verify a proof function verifyDepositProof(bytes32 proofHash) external view returns (bool) { return depositProofs[proofHash]; } // Allow the contract admin to save ERC20 tokens not burned function withdrawERC20(address token, uint256 amount) external onlyOwner { require(IERC20(token).balanceOf(address(this)) >= amount, "Insufficient balance"); IERC20(token).transfer(owner(), amount); } // Allow the contract admin to save WETH function withdrawWETH(uint256 amount) external onlyOwner { require(weth.balanceOf(address(this)) >= amount, "Insufficient WETH balance"); weth.transfer(owner(), amount); } // Function to receive ETH without automatically wrapping them receive() external payable { revert("Please use depositETH function with chainDestination and networkId"); } // Utility : Convert an address to string (hexadecimal) function toAsciiString(address x) internal pure returns (string memory) { bytes memory s = new bytes(40); for (uint256 i = 0; i < 20; i++) { bytes1 b = bytes1(uint8(uint256(uint160(x)) / (2**(8*(19 - i))))); bytes1 hi = bytes1(uint8(b) / 16); bytes1 lo = bytes1(uint8(b) - 16 * uint8(hi)); s[2*i] = char(hi); s[2*i+1] = char(lo); } return string(s); } function char(bytes1 b) internal pure returns (bytes1 c) { if (uint8(b) < 10) return bytes1(uint8(b) + 0x30); else return bytes1(uint8(b) + 0x57); } // Utility : Convert a uint to string function uint2str(uint256 _i) internal pure returns (string memory str) { if (_i == 0) return "0"; uint256 j = _i; uint256 len; while (j != 0) { len++; j /= 10; } bytes memory bstr = new bytes(len); uint256 k = len; while (_i != 0) { k = k-1; uint8 temp = (48 + uint8(_i - _i / 10 * 10)); bytes1 b1 = bytes1(temp); bstr[k] = b1; _i /= 10; } str = string(bstr); } function setChiefValidator(address payable _chiefValidator) external onlyOwner { require(_chiefValidator != address(0), "Invalid address"); uint256 codeSize; assembly { codeSize := extcodesize(_chiefValidator) } require(codeSize > 0, "Address is not a contract"); chiefValidator = ChiefValidator(_chiefValidator); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; contract ChainRouter { struct ChainInfo { string chainName; uint256 networkId; } // Mapping to store registered chains mapping(uint256 => ChainInfo) public registeredChains; uint256[] public networkIds; // Event for chain management event ChainRegistered(string chainName, uint256 networkId); event ChainUnregistered(string chainName, uint256 networkId); // Contract admin for chain registration address public owner; modifier onlyOwner() { require(msg.sender == owner, "Not authorized"); _; } constructor() { owner = msg.sender; } // Function to register a new destination chain function registerChain(string calldata chainName, uint256 networkId) external onlyOwner { require(registeredChains[networkId].networkId == 0, "Chain already registered"); registeredChains[networkId] = ChainInfo(chainName, networkId); networkIds.push(networkId); emit ChainRegistered(chainName, networkId); } // Function to unregister a chain function unregisterChain(uint256 networkId) external onlyOwner { require(registeredChains[networkId].networkId != 0, "Chain not registered"); string memory chainName = registeredChains[networkId].chainName; delete registeredChains[networkId]; // Remove networkId from the array for (uint256 i = 0; i < networkIds.length; i++) { if (networkIds[i] == networkId) { networkIds[i] = networkIds[networkIds.length - 1]; networkIds.pop(); break; } } emit ChainUnregistered(chainName, networkId); } // Function to check if a chain is registered function isChainRegistered(uint256 networkId) external view returns (bool) { return registeredChains[networkId].networkId != 0; } // Function to get chain info function getChainInfo(uint256 networkId) external view returns (string memory, uint256) { require(registeredChains[networkId].networkId != 0, "Chain not registered"); ChainInfo memory chain = registeredChains[networkId]; return (chain.chainName, chain.networkId); } // Function to get all registered chains function getAllRegisteredChains() external view returns (ChainInfo[] memory) { ChainInfo[] memory chains = new ChainInfo[](networkIds.length); for (uint256 i = 0; i < networkIds.length; i++) { chains[i] = registeredChains[networkIds[i]]; } return chains; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IWETH { function deposit() external payable; function withdraw(uint256 wad) external; function balanceOf(address guy) external view returns (uint256); function transfer(address dst, uint256 wad) external returns (bool); function approve(address usr, uint256 wad) external returns (bool); function transferFrom(address src, address dst, uint256 wad) external returns (bool); function allowance(address src, address dst) external view returns (uint256); event Deposit(address indexed dst, uint256 wad); event Withdrawal(address indexed src, uint256 wad); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./sources/OZ/Ownable.sol"; import "./sources/OZ/ReentrancyGuard.sol"; import "./sources/OZ/IERC20.sol"; import "./sources/OZ/Address.sol"; import "./sources/IWETH.sol"; import "./sources/IMintableERC20.sol"; import "./sources/IBridgedToken.sol"; import "./validatorFactory.sol"; import "./validator.sol"; interface IBurnableERC20 { function burn(uint256 amount) external; } contract ChiefValidator is Ownable, ReentrancyGuard { address public EMLTokenAddress; ValidatorFactory public validatorFactory; uint256 public emlRewardAmount; address public bridgeDeposit; address public wethAddress; address public devAddress; IWETH public weth; // Retreive Bridge Tokens mapping(address => bool) public bridgeTokens; // Store Proofs mapping(bytes32 => bool) public proofs; // bool => true (legit) or false (not submitted or fraud) // Mapping of authorized Contracts mapping(address => bool) public authorizedContracts; // Events event TokenDeployed(address indexed initialOwner, address indexed tokenAddress, string name, string symbol); event ProofVerified(bytes32 indexed proofHash, bool valid); event EMLMinted(address indexed validator, uint256 amount); event BridgeTokenRegistered(address indexed tokenAddress); event BridgedETH(address to, uint256 amount); event BridgeFee(address to, uint256 amount); event TokenBridgedIn(address indexed tokenAddress, address to, uint256 amount); event BridgedTokenTransfered(address indexed tokenAddress, address to, uint256 amount); event DeployerAuthorized(address indexed contractAddress, bool isAuthorized); // Modifier modifier onlyAuthorized() { require(authorizedContracts[msg.sender], "Caller is not authorized"); _; } constructor( address _EMLTokenAddress, address _wethAddress, address _devAddress, address _initialOwner, address _validatorFactory ) Ownable(_initialOwner) { EMLTokenAddress = _EMLTokenAddress; validatorFactory = ValidatorFactory(_validatorFactory); wethAddress = _wethAddress; devAddress = _devAddress; transferOwnership(_initialOwner); } // Autorize contracts for validator creation function setAuthorization(address _contract, bool _isAuthorized) external onlyOwner { authorizedContracts[_contract] = _isAuthorized; emit DeployerAuthorized(_contract, _isAuthorized); } // Register Bridge Tokens function registerBridgeTokens(address[] calldata tokens) external onlyAuthorized { for (uint256 i = 0; i < tokens.length; i++) { bridgeTokens[tokens[i]] = true; emit BridgeTokenRegistered(tokens[i]); } } // Update Bridge Tokens function updateBridgeTokens(address tokenAddress, bool isRegistered) external onlyOwner { bridgeTokens[tokenAddress] = isRegistered; } function isBridgeTokenRegistered(address token) external view returns (bool) { return bridgeTokens[token]; } // Verify Proof & Mint EML Rewards to validators function verifyProof(string[] calldata proofData, bytes32 proofHash) external nonReentrant onlyOwner { require(proofData.length == 6, "Invalid proof data length"); require(!proofs[proofHash], "Proof already submitted"); address[] memory validators = validatorFactory.getDeployedValidators(); uint256 activeValidatorCount = 0; address[] memory activeValidators = new address[](validators.length); for (uint256 i = 0; i < validators.length; i++) { if (Validator(validators[i]).isActive()) { activeValidators[activeValidatorCount] = validators[i]; activeValidatorCount++; } } require(activeValidatorCount > 0, "No active validators found"); bool proofValid = false; for (uint256 i = 0; i < activeValidatorCount; i++) { bytes32 keccakResult = Validator(activeValidators[i]).calculateKeccak256(proofData); if (keccakResult == proofHash) { proofValid = true; break; } } if (proofValid) { mintEMLRewards(); handleBridgedToken(proofData); proofs[proofHash] = true; emit ProofVerified(proofHash, true); } else { emit ProofVerified(proofHash, false); } } // Mint EML Rewards function mintEMLRewards() internal { address[] memory validators = validatorFactory.getDeployedValidators(); uint256 totalActiveValidators = 0; // Number of active Validators for (uint256 i = 0; i < validators.length; i++) { if (Validator(validators[i]).isActive()) { totalActiveValidators++; } } require(totalActiveValidators > 0, "No active validators found"); uint256 rewardPerValidator = emlRewardAmount / totalActiveValidators; // EML Mint to Active Validators only & equally for (uint256 i = 0; i < validators.length; i++) { if (Validator(validators[i]).isActive()) { address validatorOwner = Validator(validators[i]).getValidatorOwner(); // Call EML Mint function IMintableERC20(EMLTokenAddress).mint(validatorOwner, rewardPerValidator); emit EMLMinted(validatorOwner, rewardPerValidator); } } } // Handle Bridge Operations function handleBridgedToken(string[] calldata proofData) internal { address tokenAddress = parseAddress(proofData[0]); uint256 amount = parseUint(proofData[1]); address destination = parseAddress(proofData[2]); uint256 timestamp = parseUint(proofData[3]); string memory emoliumSaltData = proofData[4]; uint256 providedFee = parseUint(proofData[5]); require(timestamp >= 0, "Invalid timestamp"); require(bytes(emoliumSaltData).length > 0, "Invalid salt data"); require(providedFee >= 0, "Invalid fee"); // Fee calculation and validation uint256 calculatedFee = (amount * providedFee) / 10000; uint256 netAmount = amount - calculatedFee; // Handle ETH & WETH if (tokenAddress == wethAddress) { IWETH(wethAddress).withdraw(amount); payable(devAddress).transfer(calculatedFee); payable(destination).transfer(netAmount); emit BridgedETH(destination, netAmount); if (calculatedFee > 0) emit BridgeFee(devAddress, calculatedFee); } // Handle Emolium Bridge Registered Token else if (bridgeTokens[tokenAddress]) { IBridgedToken(tokenAddress).mint(destination, netAmount); IBridgedToken(tokenAddress).mint(devAddress, calculatedFee); emit TokenBridgedIn(tokenAddress, destination, netAmount); if (calculatedFee > 0) emit BridgeFee(devAddress, calculatedFee); } // Handle all other ERC20 tokens else { IERC20(tokenAddress).transfer(destination, netAmount); IERC20(tokenAddress).transfer(devAddress, calculatedFee); emit BridgedTokenTransfered(tokenAddress, destination, netAmount); if (calculatedFee > 0) emit BridgeFee(devAddress, calculatedFee); } } // Convert string to uint function parseUint(string memory _value) internal pure returns (uint256) { bytes memory b = bytes(_value); uint256 number = 0; for (uint256 i = 0; i < b.length; i++) { number = number * 10 + (uint256(uint8(b[i])) - 48); } return number; } // Convert string to address function parseAddress(string memory _value) internal pure returns (address) { bytes memory b = bytes(_value); require(b.length == 42, "Invalid address length"); // Inclut '0x' au début uint160 number; for (uint256 i = 2; i < b.length; i++) { // Skip '0x' number *= 16; uint8 c = uint8(b[i]); if (c >= 48 && c <= 57) { number += c - 48; } else if (c >= 97 && c <= 102) { number += c - 87; } else if (c >= 65 && c <= 70) { number += c - 55; } } return address(number); } // Setters for addresses function setBridgeDeposit(address _bridgeDeposit) external onlyOwner { bridgeDeposit = _bridgeDeposit; } function setWethAddress(address _wethAddress) external onlyOwner { wethAddress = _wethAddress; } // Set EML Reward Amount function setEMLRewardAmount(uint256 _amount) external onlyOwner { emlRewardAmount = _amount; } // Get Proof Status function getProofStatus(bytes32 proofHash) external view returns (bool) { return proofs[proofHash]; } // Emergency & Rescue Functions function rescueETH() external onlyOwner { require(address(this).balance > 0, "Insufficient ETH balance"); payable(devAddress).transfer(address(this).balance); } function rescueERC20(address token, uint256 amount) external onlyOwner { IERC20 erc20 = IERC20(token); require(erc20.balanceOf(address(this)) >= amount, "Insufficient token balance"); erc20.transfer(devAddress, amount); } function rescueWETH(uint256 amount) external onlyOwner { require(weth.balanceOf(address(this)) >= amount, "Insufficient WETH balance"); weth.transfer(devAddress, amount); } receive() external payable {} }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.20; import "./Context.sol"; abstract contract Ownable is Context { address private _owner; error OwnableUnauthorizedAccount(address account); error OwnableInvalidOwner(address owner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); constructor(address initialOwner) { if (initialOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(initialOwner); } modifier onlyOwner() { _checkOwner(); _; } function owner() public view virtual returns (address) { return _owner; } function _checkOwner() internal view virtual { if (owner() != _msgSender()) { revert OwnableUnauthorizedAccount(_msgSender()); } } function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } function transferOwnership(address newOwner) public virtual onlyOwner { if (newOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(newOwner); } function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/ERC20Burnable.sol) pragma solidity ^0.8.20; import "./ERC20.sol"; import "./Context.sol"; abstract contract ERC20Burnable is Context, ERC20 { function burn(uint256 value) public virtual { _burn(_msgSender(), value); } function burnFrom(address account, uint256 value) public virtual { _spendAllowance(account, _msgSender(), value); _burn(account, value); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/ReentrancyGuard.sol) pragma solidity ^0.8.20; abstract contract ReentrancyGuard { uint256 private constant NOT_ENTERED = 1; uint256 private constant ENTERED = 2; uint256 private _status; error ReentrancyGuardReentrantCall(); constructor() { _status = NOT_ENTERED; } modifier nonReentrant() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { if (_status == ENTERED) { revert ReentrancyGuardReentrantCall(); } _status = ENTERED; } function _nonReentrantAfter() private { _status = NOT_ENTERED; } function _reentrancyGuardEntered() internal view returns (bool) { return _status == ENTERED; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; interface IERC20 { event Transfer(address indexed from, address indexed to, uint256 value); event Approval(address indexed owner, address indexed spender, uint256 value); function totalSupply() external view returns (uint256); function balanceOf(address account) external view returns (uint256); function transfer(address to, uint256 value) external returns (bool); function allowance(address owner, address spender) external view returns (uint256); function approve(address spender, uint256 value) external returns (bool); function transferFrom(address from, address to, uint256 value) external returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IMintableERC20 { function mint(address to, uint256 amount) external; function burn(address from, uint256 amount) external; function transfer(address to, uint256 amount) external returns (bool); function transferFrom(address from, address to, uint256 amount) external returns (bool); function approve(address spender, uint256 amount) external returns (bool); function allowance(address owner, address spender) external view returns (uint256); function totalSupply() external view returns (uint256); function balanceOf(address account) external view returns (uint256); function decimals() external view returns (uint8); function symbol() external view returns (string memory); function name() external view returns (string memory); function tokenAddress() external view returns (address); function mintable() external view returns (bool); function burnable() external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/ERC20.sol) pragma solidity ^0.8.20; import "./IERC20.sol"; import "./IERC20Metadata.sol"; import "./Context.sol"; import "./draft-IERC6093.sol"; abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors { mapping(address account => uint256) private _balances; mapping(address account => mapping(address spender => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } function name() public view virtual returns (string memory) { return _name; } function symbol() public view virtual returns (string memory) { return _symbol; } function decimals() public view virtual returns (uint8) { return 18; } function totalSupply() public view virtual returns (uint256) { return _totalSupply; } function balanceOf(address account) public view virtual returns (uint256) { return _balances[account]; } function transfer(address to, uint256 value) public virtual returns (bool) { address owner = _msgSender(); _transfer(owner, to, value); return true; } function allowance(address owner, address spender) public view virtual returns (uint256) { return _allowances[owner][spender]; } function approve(address spender, uint256 value) public virtual returns (bool) { address owner = _msgSender(); _approve(owner, spender, value); return true; } function transferFrom(address from, address to, uint256 value) public virtual returns (bool) { address spender = _msgSender(); _spendAllowance(from, spender, value); _transfer(from, to, value); return true; } function _transfer(address from, address to, uint256 value) internal { if (from == address(0)) { revert ERC20InvalidSender(address(0)); } if (to == address(0)) { revert ERC20InvalidReceiver(address(0)); } _update(from, to, value); } function _update(address from, address to, uint256 value) internal virtual { if (from == address(0)) { _totalSupply += value; } else { uint256 fromBalance = _balances[from]; if (fromBalance < value) { revert ERC20InsufficientBalance(from, fromBalance, value); } unchecked { _balances[from] = fromBalance - value; } } if (to == address(0)) { unchecked { _totalSupply -= value; } } else { unchecked { _balances[to] += value; } } emit Transfer(from, to, value); } function _mint(address account, uint256 value) internal { if (account == address(0)) { revert ERC20InvalidReceiver(address(0)); } _update(address(0), account, value); } function _burn(address account, uint256 value) internal { if (account == address(0)) { revert ERC20InvalidSender(address(0)); } _update(account, address(0), value); } function _approve(address owner, address spender, uint256 value) internal { _approve(owner, spender, value, true); } function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual { if (owner == address(0)) { revert ERC20InvalidApprover(address(0)); } if (spender == address(0)) { revert ERC20InvalidSpender(address(0)); } _allowances[owner][spender] = value; if (emitEvent) { emit Approval(owner, spender, value); } } function _spendAllowance(address owner, address spender, uint256 value) internal virtual { uint256 currentAllowance = allowance(owner, spender); if (currentAllowance != type(uint256).max) { if (currentAllowance < value) { revert ERC20InsufficientAllowance(spender, currentAllowance, value); } unchecked { _approve(owner, spender, currentAllowance - value, false); } } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./sources/OZ/IERC20.sol"; import "./sources/OZ/Ownable.sol"; contract Validator is Ownable { address public EMLTokenAddress; address public validatorFactory; uint256 public validatorPrice; address public admin; bool public active = false; // Validator Current Owner mapping(address => address) public validatorOwners; // Mapping to associate the contract address with the validator address mapping(address => address) public validatorContracts; // Events event EMLBalanceChecked(uint256 balance); event ValidatorCount(uint256 activeCount, uint256 maxCount); event ValidatorClosed(address indexed owner, uint256 amount); event ValidatorOpened(); event ValidatorClosedEvent(); constructor(address _EMLTokenAddress, address _initialOwner, address _validatorFactory) Ownable(_initialOwner) { EMLTokenAddress = _EMLTokenAddress; admin = _initialOwner; validatorFactory = _validatorFactory; // Set the validatorFactory by default validatorContracts[address(this)] = address(this); validatorOwners[address(this)] = _initialOwner; } // Keccak hash function for an array of strings function calculateKeccak256(string[] calldata inputs) external view returns (bytes32) { require(active, "Validator is not active"); // Check if the validator is active // Concatenate all strings in the array bytes memory concatenatedString; for (uint256 i = 0; i < inputs.length; i++) { concatenatedString = abi.encodePacked(concatenatedString, inputs[i]); } // Calculate the Keccak256 hash of the concatenated string bytes32 hash = keccak256(concatenatedString); return hash; } // Set a new validator factory function setValidatorFactory(address _validatorFactory) external onlyOwner { require(_validatorFactory != address(0), "Invalid validator factory address"); validatorFactory = _validatorFactory; } // Return the validator contract address function getValidatorContractAddress() external view returns (address) { return validatorContracts[address(this)]; } // Return the current validator owner function getValidatorOwner() external view returns (address) { return validatorOwners[address(this)]; } // Return the amount of EML available in the contract function getEMLBalance() external view returns (uint256) { return IERC20(EMLTokenAddress).balanceOf(address(this)); } // Function to close the validator and send the EML balance to the owner function closeValidator() external onlyOwner { uint256 balance = IERC20(EMLTokenAddress).balanceOf(address(this)); require(balance > 0, "No EML tokens to transfer"); IERC20(EMLTokenAddress).transfer(owner(), balance); active = false; emit ValidatorClosed(owner(), balance); emit ValidatorClosedEvent(); } // Open the validator if it holds at least 20,000 EML function openValidator() external onlyOwner { uint256 emlBalance = IERC20(EMLTokenAddress).balanceOf(address(this)); emit EMLBalanceChecked(emlBalance); // Log la balance require(emlBalance >= 20000 * 10**18, "Validator must hold at least 20,000 EML"); active = true; emit ValidatorOpened(); } // Function to check if the validator is active function isActive() external view returns (bool) { return active; } // Function to get the admin address function getAdmin() external view returns (address) { return admin; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./sources/OZ/Ownable.sol"; import "./validator.sol"; contract ValidatorFactory is Ownable { // Mapping to store the addresses of deployed validators mapping(address => bool) public validators; // Mapping of authorized Contracts mapping(address => bool) public authorizedContracts; // List of deployed validators address[] public deployedValidators; // Maximum number of active validators uint256 public constant MAX_ACTIVE_VALIDATORS = 25; // Events event ValidatorCreated(address indexed validatorAddress); event ContractAuthorized(address indexed contractAddress, bool isAuthorized); // Modifier modifier onlyAuthorized() { require(authorizedContracts[msg.sender], "Caller is not authorized"); _; } constructor(address _initialOwner) Ownable(_initialOwner) { } // Autorize contracts for validator creation function setAuthorization(address _contract, bool _isAuthorized) external onlyOwner { authorizedContracts[_contract] = _isAuthorized; emit ContractAuthorized(_contract, _isAuthorized); } // Function to create a single Validator and assign ownership to the provided owner function createValidator(address _EMLTokenAddress, address _owner) external onlyAuthorized returns (address) { // Check the number of active validators uint256 activeValidatorCount = 0; for (uint256 i = 0; i < deployedValidators.length; i++) { if (Validator(deployedValidators[i]).isActive()) { activeValidatorCount++; } } require( activeValidatorCount < MAX_ACTIVE_VALIDATORS, "Maximum number of active validators reached" ); // Create the validator and pass this factory address in the constructor Validator newValidator = new Validator(_EMLTokenAddress, _owner, address(this)); // Register the new validator in the factory address validatorAddress = address(newValidator); validators[validatorAddress] = true; deployedValidators.push(validatorAddress); emit ValidatorCreated(validatorAddress); return validatorAddress; } // Create a batch of Validators function createInitialValidators(address _EMLTokenAddress, uint256 numberOfValidators) external onlyOwner { require(numberOfValidators > 0, "Number of validators must be greater than 0"); require(numberOfValidators <= MAX_ACTIVE_VALIDATORS, "Cannot create more than the maximum allowed validators"); // Check active Validators number uint256 activeValidatorCount = 0; for (uint256 i = 0; i < deployedValidators.length; i++) { if (Validator(deployedValidators[i]).isActive()) { activeValidatorCount++; } } require( deployedValidators.length + numberOfValidators <= MAX_ACTIVE_VALIDATORS || activeValidatorCount < MAX_ACTIVE_VALIDATORS, "Cannot exceed the maximum number of validators" ); for (uint256 i = 0; i < numberOfValidators; i++) { Validator newValidator = new Validator(_EMLTokenAddress, msg.sender, address(this)); address validatorAddress = address(newValidator); validators[validatorAddress] = true; deployedValidators.push(validatorAddress); emit ValidatorCreated(validatorAddress); } } // Check if a validator is active function isValidatorActive(address validatorAddress) external view returns (bool) { require(validators[validatorAddress], "Validator not found"); return Validator(validatorAddress).isActive(); } // Get the owner of a validator function getValidatorOwner(address validatorAddress) external view returns (address) { require(validators[validatorAddress], "Validator not found"); return Validator(validatorAddress).getValidatorOwner(); } // Get the list of deployed validators function getDeployedValidators() external view returns (address[] memory) { return deployedValidators; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IBridgedToken { function mint(address to, uint256 amount) external; function burn(address from, uint256 amount) external; function burnFrom(address from, uint256 amount) external; function transfer(address to, uint256 amount) external returns (bool); function transferFrom(address from, address to, uint256 amount) external returns (bool); function approve(address spender, uint256 amount) external returns (bool); function allowance(address owner, address spender) external view returns (uint256); function totalSupply() external view returns (uint256); function balanceOf(address account) external view returns (uint256); function decimals() external view returns (uint8); function symbol() external view returns (string memory); function name() external view returns (string memory); function tokenAddress() external view returns (address); function mintable() external view returns (bool); function burnable() external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol) pragma solidity ^0.8.20; import "./Errors.sol"; library Address { error AddressEmptyCode(address target); function sendValue(address payable recipient, uint256 amount) internal { if (address(this).balance < amount) { revert Errors.InsufficientBalance(address(this).balance, amount); } (bool success, ) = recipient.call{value: amount}(""); if (!success) { revert Errors.FailedCall(); } } function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0); } function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { if (address(this).balance < value) { revert Errors.InsufficientBalance(address(this).balance, value); } (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata); } function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata); } function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata); } function verifyCallResultFromTarget( address target, bool success, bytes memory returndata ) internal view returns (bytes memory) { if (!success) { _revert(returndata); } else { if (returndata.length == 0 && target.code.length == 0) { revert AddressEmptyCode(target); } return returndata; } } function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) { if (!success) { _revert(returndata); } else { return returndata; } } function _revert(bytes memory returndata) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly assembly ("memory-safe") { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert Errors.FailedCall(); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC6093.sol) pragma solidity ^0.8.20; interface IERC20Errors { error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed); error ERC20InvalidSender(address sender); error ERC20InvalidReceiver(address receiver); error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed); error ERC20InvalidApprover(address approver); error ERC20InvalidSpender(address spender); } interface IERC721Errors { error ERC721InvalidOwner(address owner); error ERC721NonexistentToken(uint256 tokenId); error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner); error ERC721InvalidSender(address sender); error ERC721InvalidReceiver(address receiver); error ERC721InsufficientApproval(address operator, uint256 tokenId); error ERC721InvalidApprover(address approver); error ERC721InvalidOperator(address operator); } interface IERC1155Errors { error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId); error ERC1155InvalidSender(address sender); error ERC1155InvalidReceiver(address receiver); error ERC1155MissingApprovalForAll(address operator, address owner); error ERC1155InvalidApprover(address approver); error ERC1155InvalidOperator(address operator); error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.20; import "./IERC20.sol"; interface IERC20Metadata is IERC20 { function name() external view returns (string memory); function symbol() external view returns (string memory); function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; library Errors { error InsufficientBalance(uint256 balance, uint256 needed); error FailedCall(); error FailedDeployment(); error MissingPrecompile(address); }
{ "optimizer": { "enabled": false, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "remappings": [] }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address payable","name":"_chiefValidator","type":"address"},{"internalType":"address","name":"_initialOwner","type":"address"},{"internalType":"address","name":"_weth","type":"address"},{"internalType":"address","name":"_chainRouter","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"depositor","type":"address"},{"indexed":false,"internalType":"bytes32","name":"proofHash","type":"bytes32"},{"indexed":false,"internalType":"string","name":"proofData","type":"string"}],"name":"DepositProofGenerated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ERC20Bridged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ERC20Deposited","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ETHDeposited","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[],"name":"chainRouter","outputs":[{"internalType":"contract ChainRouter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"chiefValidator","outputs":[{"internalType":"contract ChiefValidator","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"string","name":"chainDestination","type":"string"},{"internalType":"uint256","name":"networkId","type":"uint256"}],"name":"depositERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"chainDestination","type":"string"},{"internalType":"uint256","name":"networkId","type":"uint256"}],"name":"depositETH","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"depositProofs","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"_chiefValidator","type":"address"}],"name":"setChiefValidator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"proofHash","type":"bytes32"}],"name":"verifyDepositProof","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"weth","outputs":[{"internalType":"contract IWETH","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawWETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
60806040526001600555348015610014575f80fd5b50604051612caa380380612caa8339818101604052810190610036919061044a565b8260015f819055505f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036100ae575f6040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081526004016100a591906104bd565b60405180910390fd5b6100bd8161019660201b60201c565b508360025f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508160035f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508060045f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061018d8361025960201b60201c565b505050506104d6565b5f60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508160015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6102676102e960201b60201c565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036102d7575f6040517f1e4fbdf70000000000000000000000000000000000000000000000000000000081526004016102ce91906104bd565b60405180910390fd5b6102e68161019660201b60201c565b50565b6102f761038260201b60201c565b73ffffffffffffffffffffffffffffffffffffffff1661031b61038960201b60201c565b73ffffffffffffffffffffffffffffffffffffffff16146103805761034461038260201b60201c565b6040517f118cdaa700000000000000000000000000000000000000000000000000000000815260040161037791906104bd565b60405180910390fd5b565b5f33905090565b5f60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6103de826103b5565b9050919050565b6103ee816103d4565b81146103f8575f80fd5b50565b5f81519050610409816103e5565b92915050565b5f610419826103b5565b9050919050565b6104298161040f565b8114610433575f80fd5b50565b5f8151905061044481610420565b92915050565b5f805f8060808587031215610462576104616103b1565b5b5f61046f878288016103fb565b945050602061048087828801610436565b935050604061049187828801610436565b92505060606104a287828801610436565b91505092959194509250565b6104b78161040f565b82525050565b5f6020820190506104d05f8301846104ae565b92915050565b6127c7806104e35f395ff3fe6080604052600436106100c5575f3560e01c80638da5cb5b1161007e578063ca080d0a11610058578063ca080d0a14610281578063eb246296146102ab578063f2fde38b146102d3578063fc4dd333146102fb57610105565b80638da5cb5b14610205578063a1db97821461022f578063a2e03da41461025757610105565b80631d01ac0e146101095780633fc8cef3146101455780635c1b40161461016f578063630a47c714610197578063672f345d146101d3578063715018a6146101ef57610105565b36610105576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100fc90611794565b60405180910390fd5b5f80fd5b348015610114575f80fd5b5061012f600480360381019061012a91906117f6565b610323565b60405161013c919061183b565b60405180910390f35b348015610150575f80fd5b50610159610340565b60405161016691906118ce565b60405180910390f35b34801561017a575f80fd5b5061019560048036038101906101909190611a91565b610365565b005b3480156101a2575f80fd5b506101bd60048036038101906101b891906117f6565b6107f3565b6040516101ca919061183b565b60405180910390f35b6101ed60048036038101906101e89190611b11565b610819565b005b3480156101fa575f80fd5b50610203610be9565b005b348015610210575f80fd5b50610219610bfc565b6040516102269190611b7a565b60405180910390f35b34801561023a575f80fd5b5061025560048036038101906102509190611b93565b610c24565b005b348015610262575f80fd5b5061026b610d6d565b6040516102789190611c02565b60405180910390f35b34801561028c575f80fd5b50610295610d92565b6040516102a29190611c3b565b60405180910390f35b3480156102b6575f80fd5b506102d160048036038101906102cc9190611c8f565b610db7565b005b3480156102de575f80fd5b506102f960048036038101906102f49190611cba565b610eb8565b005b348015610306575f80fd5b50610321600480360381019061031c9190611ce5565b610f3c565b005b6006602052805f5260405f205f915054906101000a900460ff1681565b60035f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b61036d6110c6565b5f83116103af576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103a690611d5a565b60405180910390fd5b60045f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b9e06402826040518263ffffffff1660e01b81526004016104099190611d87565b602060405180830381865afa158015610424573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104489190611dca565b610487576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161047e90611e3f565b60405180910390fd5b8373ffffffffffffffffffffffffffffffffffffffff166323b872dd3330866040518463ffffffff1660e01b81526004016104c493929190611e5d565b6020604051808303815f875af11580156104e0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105049190611dca565b610543576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161053a90611edc565b60405180910390fd5b5f6105503386868661110a565b90505f816040516020016105649190611f4c565b604051602081830303815290604052805190602001209050600160065f8381526020019081526020015f205f6101000a81548160ff02191690831515021790555060025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16636866a817876040518263ffffffff1660e01b81526004016105ff9190611b7a565b602060405180830381865afa15801561061a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061063e9190611dca565b156106525761064d868661115e565b610793565b8573ffffffffffffffffffffffffffffffffffffffff1663a9059cbb60025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16876040518363ffffffff1660e01b81526004016106ae929190611f62565b6020604051808303815f875af11580156106ca573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106ee9190611dca565b61072d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161072490611ff9565b60405180910390fd5b8573ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fe33e9822e3317b004d587136bab2627ea1ecfbba4eb79abddd0a56cfdd09c0e18760405161078a9190611d87565b60405180910390a35b3373ffffffffffffffffffffffffffffffffffffffff167ff8ec0b7ce5fdd783b80282fd8869c4b656af961aac24ac89c89fb8d94b9b809f82846040516107db92919061205e565b60405180910390a250506107ed61121b565b50505050565b5f60065f8381526020019081526020015f205f9054906101000a900460ff169050919050565b6108216110c6565b5f3411610863576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161085a906120d6565b60405180910390fd5b60045f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b9e06402826040518263ffffffff1660e01b81526004016108bd9190611d87565b602060405180830381865afa1580156108d8573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108fc9190611dca565b61093b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161093290611e3f565b60405180910390fd5b60035f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d0e30db0346040518263ffffffff1660e01b81526004015f604051808303818588803b1580156109a2575f80fd5b505af11580156109b4573d5f803e3d5ffd5b50505050505f34905060035f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb60025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836040518363ffffffff1660e01b8152600401610a3a929190611f62565b6020604051808303815f875af1158015610a56573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a7a9190611dca565b610ab9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ab090611ff9565b60405180910390fd5b5f610ae73360035f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16848761110a565b90505f81604051602001610afb9190611f4c565b604051602081830303815290604052805190602001209050600160065f8381526020019081526020015f205f6101000a81548160ff0219169083151502179055503373ffffffffffffffffffffffffffffffffffffffff167f6c703791f399558807424f489ccd811c72b4ff0b74af547264fad7c646776df084604051610b829190611d87565b60405180910390a23373ffffffffffffffffffffffffffffffffffffffff167ff8ec0b7ce5fdd783b80282fd8869c4b656af961aac24ac89c89fb8d94b9b809f8284604051610bd292919061205e565b60405180910390a2505050610be561121b565b5050565b610bf1611224565b610bfa5f6112ab565b565b5f60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b610c2c611224565b808273ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610c669190611b7a565b602060405180830381865afa158015610c81573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ca59190612108565b1015610ce6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cdd9061217d565b60405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff1663a9059cbb610d0a610bfc565b836040518363ffffffff1660e01b8152600401610d28929190611f62565b6020604051808303815f875af1158015610d44573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d689190611dca565b505050565b60025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60045f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b610dbf611224565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610e2d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e24906121e5565b60405180910390fd5b5f813b90505f8111610e74576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e6b9061224d565b60405180910390fd5b8160025f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b610ec0611224565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610f30575f6040517f1e4fbdf7000000000000000000000000000000000000000000000000000000008152600401610f279190611b7a565b60405180910390fd5b610f39816112ab565b50565b610f44611224565b8060035f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610f9f9190611b7a565b602060405180830381865afa158015610fba573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610fde9190612108565b101561101f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611016906122b5565b60405180910390fd5b60035f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb611064610bfc565b836040518363ffffffff1660e01b8152600401611082929190611f62565b6020604051808303815f875af115801561109e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110c29190611dca565b5050565b60025f5403611101576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60025f81905550565b60606111158561136e565b61111e8561136e565b61112785611524565b61113042611524565b8560405160200161114595949392919061231d565b6040516020818303038152906040529050949350505050565b5f8290508073ffffffffffffffffffffffffffffffffffffffff166342966c68836040518263ffffffff1660e01b815260040161119b9190611d87565b5f604051808303815f87803b1580156111b2575f80fd5b505af11580156111c4573d5f803e3d5ffd5b505050508273ffffffffffffffffffffffffffffffffffffffff167f5138d4c70db2cb3c71272ed7eb2caca17373b1a6f0cc5a0b632fb82b2a2871af8360405161120e9190611d87565b60405180910390a2505050565b60015f81905550565b61122c6116a2565b73ffffffffffffffffffffffffffffffffffffffff1661124a610bfc565b73ffffffffffffffffffffffffffffffffffffffff16146112a95761126d6116a2565b6040517f118cdaa70000000000000000000000000000000000000000000000000000000081526004016112a09190611b7a565b60405180910390fd5b565b5f60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508160015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b60605f602867ffffffffffffffff81111561138c5761138b61196d565b5b6040519080825280601f01601f1916602001820160405280156113be5781602001600182028036833780820191505090505b5090505f5b601481101561151a575f8160136113da91906123c0565b60086113e691906123f3565b60026113f29190612563565b8573ffffffffffffffffffffffffffffffffffffffff1661141391906125da565b60f81b90505f60108260f81c6114299190612616565b60f81b90505f8160f81c601061143f9190612646565b8360f81c61144d9190612682565b60f81b905061145b826116a9565b8585600261146991906123f3565b8151811061147a576114796126b6565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053506114b1816116a9565b8560018660026114c191906123f3565b6114cb91906126e3565b815181106114dc576114db6126b6565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a90535050505080806001019150506113c3565b5080915050919050565b60605f820361156a576040518060400160405280600181526020017f3000000000000000000000000000000000000000000000000000000000000000815250905061169d565b5f8290505f5b5f821461159957808061158290612716565b915050600a8261159291906125da565b9150611570565b5f8167ffffffffffffffff8111156115b4576115b361196d565b5b6040519080825280601f01601f1916602001820160405280156115e65781602001600182028036833780820191505090505b5090505f8290505b5f86146116955760018161160291906123c0565b90505f600a808861161391906125da565b61161d91906123f3565b8761162891906123c0565b6030611634919061275d565b90505f8160f81b905080848481518110611651576116506126b6565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a905350600a8861168c91906125da565b975050506115ee565b819450505050505b919050565b5f33905090565b5f600a8260f81c60ff1610156116d35760308260f81c6116c9919061275d565b60f81b90506116e9565b60578260f81c6116e3919061275d565b60f81b90505b919050565b5f82825260208201905092915050565b7f506c6561736520757365206465706f7369744554482066756e6374696f6e20775f8201527f69746820636861696e44657374696e6174696f6e20616e64206e6574776f726b60208201527f4964000000000000000000000000000000000000000000000000000000000000604082015250565b5f61177e6042836116ee565b9150611789826116fe565b606082019050919050565b5f6020820190508181035f8301526117ab81611772565b9050919050565b5f604051905090565b5f80fd5b5f80fd5b5f819050919050565b6117d5816117c3565b81146117df575f80fd5b50565b5f813590506117f0816117cc565b92915050565b5f6020828403121561180b5761180a6117bb565b5b5f611818848285016117e2565b91505092915050565b5f8115159050919050565b61183581611821565b82525050565b5f60208201905061184e5f83018461182c565b92915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f819050919050565b5f61189661189161188c84611854565b611873565b611854565b9050919050565b5f6118a78261187c565b9050919050565b5f6118b88261189d565b9050919050565b6118c8816118ae565b82525050565b5f6020820190506118e15f8301846118bf565b92915050565b5f6118f182611854565b9050919050565b611901816118e7565b811461190b575f80fd5b50565b5f8135905061191c816118f8565b92915050565b5f819050919050565b61193481611922565b811461193e575f80fd5b50565b5f8135905061194f8161192b565b92915050565b5f80fd5b5f80fd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6119a38261195d565b810181811067ffffffffffffffff821117156119c2576119c161196d565b5b80604052505050565b5f6119d46117b2565b90506119e0828261199a565b919050565b5f67ffffffffffffffff8211156119ff576119fe61196d565b5b611a088261195d565b9050602081019050919050565b828183375f83830152505050565b5f611a35611a30846119e5565b6119cb565b905082815260208101848484011115611a5157611a50611959565b5b611a5c848285611a15565b509392505050565b5f82601f830112611a7857611a77611955565b5b8135611a88848260208601611a23565b91505092915050565b5f805f8060808587031215611aa957611aa86117bb565b5b5f611ab68782880161190e565b9450506020611ac787828801611941565b935050604085013567ffffffffffffffff811115611ae857611ae76117bf565b5b611af487828801611a64565b9250506060611b0587828801611941565b91505092959194509250565b5f8060408385031215611b2757611b266117bb565b5b5f83013567ffffffffffffffff811115611b4457611b436117bf565b5b611b5085828601611a64565b9250506020611b6185828601611941565b9150509250929050565b611b74816118e7565b82525050565b5f602082019050611b8d5f830184611b6b565b92915050565b5f8060408385031215611ba957611ba86117bb565b5b5f611bb68582860161190e565b9250506020611bc785828601611941565b9150509250929050565b5f611bdb8261187c565b9050919050565b5f611bec82611bd1565b9050919050565b611bfc81611be2565b82525050565b5f602082019050611c155f830184611bf3565b92915050565b5f611c258261189d565b9050919050565b611c3581611c1b565b82525050565b5f602082019050611c4e5f830184611c2c565b92915050565b5f611c5e82611854565b9050919050565b611c6e81611c54565b8114611c78575f80fd5b50565b5f81359050611c8981611c65565b92915050565b5f60208284031215611ca457611ca36117bb565b5b5f611cb184828501611c7b565b91505092915050565b5f60208284031215611ccf57611cce6117bb565b5b5f611cdc8482850161190e565b91505092915050565b5f60208284031215611cfa57611cf96117bb565b5b5f611d0784828501611941565b91505092915050565b7f416d6f756e74206d7573742062652067726561746572207468616e20300000005f82015250565b5f611d44601d836116ee565b9150611d4f82611d10565b602082019050919050565b5f6020820190508181035f830152611d7181611d38565b9050919050565b611d8181611922565b82525050565b5f602082019050611d9a5f830184611d78565b92915050565b611da981611821565b8114611db3575f80fd5b50565b5f81519050611dc481611da0565b92915050565b5f60208284031215611ddf57611dde6117bb565b5b5f611dec84828501611db6565b91505092915050565b7f44657374696e6174696f6e20636861696e206e6f7420726567697374657265645f82015250565b5f611e296020836116ee565b9150611e3482611df5565b602082019050919050565b5f6020820190508181035f830152611e5681611e1d565b9050919050565b5f606082019050611e705f830186611b6b565b611e7d6020830185611b6b565b611e8a6040830184611d78565b949350505050565b7f5472616e73666572206661696c656400000000000000000000000000000000005f82015250565b5f611ec6600f836116ee565b9150611ed182611e92565b602082019050919050565b5f6020820190508181035f830152611ef381611eba565b9050919050565b5f81519050919050565b5f81905092915050565b8281835e5f83830152505050565b5f611f2682611efa565b611f308185611f04565b9350611f40818560208601611f0e565b80840191505092915050565b5f611f578284611f1c565b915081905092915050565b5f604082019050611f755f830185611b6b565b611f826020830184611d78565b9392505050565b7f5472616e7366657220746f20436869656656616c696461746f72206661696c655f8201527f6400000000000000000000000000000000000000000000000000000000000000602082015250565b5f611fe36021836116ee565b9150611fee82611f89565b604082019050919050565b5f6020820190508181035f83015261201081611fd7565b9050919050565b612020816117c3565b82525050565b5f61203082611efa565b61203a81856116ee565b935061204a818560208601611f0e565b6120538161195d565b840191505092915050565b5f6040820190506120715f830185612017565b81810360208301526120838184612026565b90509392505050565b7f4d7573742073656e6420455448000000000000000000000000000000000000005f82015250565b5f6120c0600d836116ee565b91506120cb8261208c565b602082019050919050565b5f6020820190508181035f8301526120ed816120b4565b9050919050565b5f815190506121028161192b565b92915050565b5f6020828403121561211d5761211c6117bb565b5b5f61212a848285016120f4565b91505092915050565b7f496e73756666696369656e742062616c616e63650000000000000000000000005f82015250565b5f6121676014836116ee565b915061217282612133565b602082019050919050565b5f6020820190508181035f8301526121948161215b565b9050919050565b7f496e76616c6964206164647265737300000000000000000000000000000000005f82015250565b5f6121cf600f836116ee565b91506121da8261219b565b602082019050919050565b5f6020820190508181035f8301526121fc816121c3565b9050919050565b7f41646472657373206973206e6f74206120636f6e7472616374000000000000005f82015250565b5f6122376019836116ee565b915061224282612203565b602082019050919050565b5f6020820190508181035f8301526122648161222b565b9050919050565b7f496e73756666696369656e7420574554482062616c616e6365000000000000005f82015250565b5f61229f6019836116ee565b91506122aa8261226b565b602082019050919050565b5f6020820190508181035f8301526122cc81612293565b9050919050565b7f2c000000000000000000000000000000000000000000000000000000000000005f82015250565b5f612307600183611f04565b9150612312826122d3565b600182019050919050565b5f6123288288611f1c565b9150612333826122fb565b915061233f8287611f1c565b915061234a826122fb565b91506123568286611f1c565b9150612361826122fb565b915061236d8285611f1c565b9150612378826122fb565b91506123848284611f1c565b91508190509695505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6123ca82611922565b91506123d583611922565b92508282039050818111156123ed576123ec612393565b5b92915050565b5f6123fd82611922565b915061240883611922565b925082820261241681611922565b9150828204841483151761242d5761242c612393565b5b5092915050565b5f8160011c9050919050565b5f808291508390505b60018511156124895780860481111561246557612464612393565b5b60018516156124745780820291505b808102905061248285612434565b9450612449565b94509492505050565b5f826124a1576001905061255c565b816124ae575f905061255c565b81600181146124c457600281146124ce576124fd565b600191505061255c565b60ff8411156124e0576124df612393565b5b8360020a9150848211156124f7576124f6612393565b5b5061255c565b5060208310610133831016604e8410600b84101617156125325782820a90508381111561252d5761252c612393565b5b61255c565b61253f8484846001612440565b9250905081840481111561255657612555612393565b5b81810290505b9392505050565b5f61256d82611922565b915061257883611922565b92506125a57fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8484612492565b905092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f6125e482611922565b91506125ef83611922565b9250826125ff576125fe6125ad565b5b828204905092915050565b5f60ff82169050919050565b5f6126208261260a565b915061262b8361260a565b92508261263b5761263a6125ad565b5b828204905092915050565b5f6126508261260a565b915061265b8361260a565b92508282026126698161260a565b915080821461267b5761267a612393565b5b5092915050565b5f61268c8261260a565b91506126978361260a565b9250828203905060ff8111156126b0576126af612393565b5b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f6126ed82611922565b91506126f883611922565b92508282019050808211156127105761270f612393565b5b92915050565b5f61272082611922565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361275257612751612393565b5b600182019050919050565b5f6127678261260a565b91506127728361260a565b9250828201905060ff81111561278b5761278a612393565b5b9291505056fea26469706673582212202bee3823fa9b27b04bac80a8cad53b0740dc067fef843f0af8e4dba64c03f56a64736f6c634300081a003300000000000000000000000062c517854f73515bca2179ef147ab45ef53b48bc00000000000000000000000092eed0282c6665c9bcc81605a13a5c3b1e4dc7f2000000000000000000000000039e2fb66102314ce7b64ce5ce3e5183bc94ad38000000000000000000000000bdfa3a2feb0673740dd6abe69a2db2c3b6459e17
Deployed Bytecode
0x6080604052600436106100c5575f3560e01c80638da5cb5b1161007e578063ca080d0a11610058578063ca080d0a14610281578063eb246296146102ab578063f2fde38b146102d3578063fc4dd333146102fb57610105565b80638da5cb5b14610205578063a1db97821461022f578063a2e03da41461025757610105565b80631d01ac0e146101095780633fc8cef3146101455780635c1b40161461016f578063630a47c714610197578063672f345d146101d3578063715018a6146101ef57610105565b36610105576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100fc90611794565b60405180910390fd5b5f80fd5b348015610114575f80fd5b5061012f600480360381019061012a91906117f6565b610323565b60405161013c919061183b565b60405180910390f35b348015610150575f80fd5b50610159610340565b60405161016691906118ce565b60405180910390f35b34801561017a575f80fd5b5061019560048036038101906101909190611a91565b610365565b005b3480156101a2575f80fd5b506101bd60048036038101906101b891906117f6565b6107f3565b6040516101ca919061183b565b60405180910390f35b6101ed60048036038101906101e89190611b11565b610819565b005b3480156101fa575f80fd5b50610203610be9565b005b348015610210575f80fd5b50610219610bfc565b6040516102269190611b7a565b60405180910390f35b34801561023a575f80fd5b5061025560048036038101906102509190611b93565b610c24565b005b348015610262575f80fd5b5061026b610d6d565b6040516102789190611c02565b60405180910390f35b34801561028c575f80fd5b50610295610d92565b6040516102a29190611c3b565b60405180910390f35b3480156102b6575f80fd5b506102d160048036038101906102cc9190611c8f565b610db7565b005b3480156102de575f80fd5b506102f960048036038101906102f49190611cba565b610eb8565b005b348015610306575f80fd5b50610321600480360381019061031c9190611ce5565b610f3c565b005b6006602052805f5260405f205f915054906101000a900460ff1681565b60035f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b61036d6110c6565b5f83116103af576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103a690611d5a565b60405180910390fd5b60045f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b9e06402826040518263ffffffff1660e01b81526004016104099190611d87565b602060405180830381865afa158015610424573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104489190611dca565b610487576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161047e90611e3f565b60405180910390fd5b8373ffffffffffffffffffffffffffffffffffffffff166323b872dd3330866040518463ffffffff1660e01b81526004016104c493929190611e5d565b6020604051808303815f875af11580156104e0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105049190611dca565b610543576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161053a90611edc565b60405180910390fd5b5f6105503386868661110a565b90505f816040516020016105649190611f4c565b604051602081830303815290604052805190602001209050600160065f8381526020019081526020015f205f6101000a81548160ff02191690831515021790555060025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16636866a817876040518263ffffffff1660e01b81526004016105ff9190611b7a565b602060405180830381865afa15801561061a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061063e9190611dca565b156106525761064d868661115e565b610793565b8573ffffffffffffffffffffffffffffffffffffffff1663a9059cbb60025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16876040518363ffffffff1660e01b81526004016106ae929190611f62565b6020604051808303815f875af11580156106ca573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106ee9190611dca565b61072d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161072490611ff9565b60405180910390fd5b8573ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fe33e9822e3317b004d587136bab2627ea1ecfbba4eb79abddd0a56cfdd09c0e18760405161078a9190611d87565b60405180910390a35b3373ffffffffffffffffffffffffffffffffffffffff167ff8ec0b7ce5fdd783b80282fd8869c4b656af961aac24ac89c89fb8d94b9b809f82846040516107db92919061205e565b60405180910390a250506107ed61121b565b50505050565b5f60065f8381526020019081526020015f205f9054906101000a900460ff169050919050565b6108216110c6565b5f3411610863576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161085a906120d6565b60405180910390fd5b60045f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b9e06402826040518263ffffffff1660e01b81526004016108bd9190611d87565b602060405180830381865afa1580156108d8573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108fc9190611dca565b61093b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161093290611e3f565b60405180910390fd5b60035f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d0e30db0346040518263ffffffff1660e01b81526004015f604051808303818588803b1580156109a2575f80fd5b505af11580156109b4573d5f803e3d5ffd5b50505050505f34905060035f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb60025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836040518363ffffffff1660e01b8152600401610a3a929190611f62565b6020604051808303815f875af1158015610a56573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a7a9190611dca565b610ab9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ab090611ff9565b60405180910390fd5b5f610ae73360035f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16848761110a565b90505f81604051602001610afb9190611f4c565b604051602081830303815290604052805190602001209050600160065f8381526020019081526020015f205f6101000a81548160ff0219169083151502179055503373ffffffffffffffffffffffffffffffffffffffff167f6c703791f399558807424f489ccd811c72b4ff0b74af547264fad7c646776df084604051610b829190611d87565b60405180910390a23373ffffffffffffffffffffffffffffffffffffffff167ff8ec0b7ce5fdd783b80282fd8869c4b656af961aac24ac89c89fb8d94b9b809f8284604051610bd292919061205e565b60405180910390a2505050610be561121b565b5050565b610bf1611224565b610bfa5f6112ab565b565b5f60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b610c2c611224565b808273ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610c669190611b7a565b602060405180830381865afa158015610c81573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ca59190612108565b1015610ce6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cdd9061217d565b60405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff1663a9059cbb610d0a610bfc565b836040518363ffffffff1660e01b8152600401610d28929190611f62565b6020604051808303815f875af1158015610d44573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d689190611dca565b505050565b60025f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60045f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b610dbf611224565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610e2d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e24906121e5565b60405180910390fd5b5f813b90505f8111610e74576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e6b9061224d565b60405180910390fd5b8160025f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b610ec0611224565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610f30575f6040517f1e4fbdf7000000000000000000000000000000000000000000000000000000008152600401610f279190611b7a565b60405180910390fd5b610f39816112ab565b50565b610f44611224565b8060035f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610f9f9190611b7a565b602060405180830381865afa158015610fba573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610fde9190612108565b101561101f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611016906122b5565b60405180910390fd5b60035f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb611064610bfc565b836040518363ffffffff1660e01b8152600401611082929190611f62565b6020604051808303815f875af115801561109e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110c29190611dca565b5050565b60025f5403611101576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60025f81905550565b60606111158561136e565b61111e8561136e565b61112785611524565b61113042611524565b8560405160200161114595949392919061231d565b6040516020818303038152906040529050949350505050565b5f8290508073ffffffffffffffffffffffffffffffffffffffff166342966c68836040518263ffffffff1660e01b815260040161119b9190611d87565b5f604051808303815f87803b1580156111b2575f80fd5b505af11580156111c4573d5f803e3d5ffd5b505050508273ffffffffffffffffffffffffffffffffffffffff167f5138d4c70db2cb3c71272ed7eb2caca17373b1a6f0cc5a0b632fb82b2a2871af8360405161120e9190611d87565b60405180910390a2505050565b60015f81905550565b61122c6116a2565b73ffffffffffffffffffffffffffffffffffffffff1661124a610bfc565b73ffffffffffffffffffffffffffffffffffffffff16146112a95761126d6116a2565b6040517f118cdaa70000000000000000000000000000000000000000000000000000000081526004016112a09190611b7a565b60405180910390fd5b565b5f60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508160015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b60605f602867ffffffffffffffff81111561138c5761138b61196d565b5b6040519080825280601f01601f1916602001820160405280156113be5781602001600182028036833780820191505090505b5090505f5b601481101561151a575f8160136113da91906123c0565b60086113e691906123f3565b60026113f29190612563565b8573ffffffffffffffffffffffffffffffffffffffff1661141391906125da565b60f81b90505f60108260f81c6114299190612616565b60f81b90505f8160f81c601061143f9190612646565b8360f81c61144d9190612682565b60f81b905061145b826116a9565b8585600261146991906123f3565b8151811061147a576114796126b6565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053506114b1816116a9565b8560018660026114c191906123f3565b6114cb91906126e3565b815181106114dc576114db6126b6565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a90535050505080806001019150506113c3565b5080915050919050565b60605f820361156a576040518060400160405280600181526020017f3000000000000000000000000000000000000000000000000000000000000000815250905061169d565b5f8290505f5b5f821461159957808061158290612716565b915050600a8261159291906125da565b9150611570565b5f8167ffffffffffffffff8111156115b4576115b361196d565b5b6040519080825280601f01601f1916602001820160405280156115e65781602001600182028036833780820191505090505b5090505f8290505b5f86146116955760018161160291906123c0565b90505f600a808861161391906125da565b61161d91906123f3565b8761162891906123c0565b6030611634919061275d565b90505f8160f81b905080848481518110611651576116506126b6565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a905350600a8861168c91906125da565b975050506115ee565b819450505050505b919050565b5f33905090565b5f600a8260f81c60ff1610156116d35760308260f81c6116c9919061275d565b60f81b90506116e9565b60578260f81c6116e3919061275d565b60f81b90505b919050565b5f82825260208201905092915050565b7f506c6561736520757365206465706f7369744554482066756e6374696f6e20775f8201527f69746820636861696e44657374696e6174696f6e20616e64206e6574776f726b60208201527f4964000000000000000000000000000000000000000000000000000000000000604082015250565b5f61177e6042836116ee565b9150611789826116fe565b606082019050919050565b5f6020820190508181035f8301526117ab81611772565b9050919050565b5f604051905090565b5f80fd5b5f80fd5b5f819050919050565b6117d5816117c3565b81146117df575f80fd5b50565b5f813590506117f0816117cc565b92915050565b5f6020828403121561180b5761180a6117bb565b5b5f611818848285016117e2565b91505092915050565b5f8115159050919050565b61183581611821565b82525050565b5f60208201905061184e5f83018461182c565b92915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f819050919050565b5f61189661189161188c84611854565b611873565b611854565b9050919050565b5f6118a78261187c565b9050919050565b5f6118b88261189d565b9050919050565b6118c8816118ae565b82525050565b5f6020820190506118e15f8301846118bf565b92915050565b5f6118f182611854565b9050919050565b611901816118e7565b811461190b575f80fd5b50565b5f8135905061191c816118f8565b92915050565b5f819050919050565b61193481611922565b811461193e575f80fd5b50565b5f8135905061194f8161192b565b92915050565b5f80fd5b5f80fd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6119a38261195d565b810181811067ffffffffffffffff821117156119c2576119c161196d565b5b80604052505050565b5f6119d46117b2565b90506119e0828261199a565b919050565b5f67ffffffffffffffff8211156119ff576119fe61196d565b5b611a088261195d565b9050602081019050919050565b828183375f83830152505050565b5f611a35611a30846119e5565b6119cb565b905082815260208101848484011115611a5157611a50611959565b5b611a5c848285611a15565b509392505050565b5f82601f830112611a7857611a77611955565b5b8135611a88848260208601611a23565b91505092915050565b5f805f8060808587031215611aa957611aa86117bb565b5b5f611ab68782880161190e565b9450506020611ac787828801611941565b935050604085013567ffffffffffffffff811115611ae857611ae76117bf565b5b611af487828801611a64565b9250506060611b0587828801611941565b91505092959194509250565b5f8060408385031215611b2757611b266117bb565b5b5f83013567ffffffffffffffff811115611b4457611b436117bf565b5b611b5085828601611a64565b9250506020611b6185828601611941565b9150509250929050565b611b74816118e7565b82525050565b5f602082019050611b8d5f830184611b6b565b92915050565b5f8060408385031215611ba957611ba86117bb565b5b5f611bb68582860161190e565b9250506020611bc785828601611941565b9150509250929050565b5f611bdb8261187c565b9050919050565b5f611bec82611bd1565b9050919050565b611bfc81611be2565b82525050565b5f602082019050611c155f830184611bf3565b92915050565b5f611c258261189d565b9050919050565b611c3581611c1b565b82525050565b5f602082019050611c4e5f830184611c2c565b92915050565b5f611c5e82611854565b9050919050565b611c6e81611c54565b8114611c78575f80fd5b50565b5f81359050611c8981611c65565b92915050565b5f60208284031215611ca457611ca36117bb565b5b5f611cb184828501611c7b565b91505092915050565b5f60208284031215611ccf57611cce6117bb565b5b5f611cdc8482850161190e565b91505092915050565b5f60208284031215611cfa57611cf96117bb565b5b5f611d0784828501611941565b91505092915050565b7f416d6f756e74206d7573742062652067726561746572207468616e20300000005f82015250565b5f611d44601d836116ee565b9150611d4f82611d10565b602082019050919050565b5f6020820190508181035f830152611d7181611d38565b9050919050565b611d8181611922565b82525050565b5f602082019050611d9a5f830184611d78565b92915050565b611da981611821565b8114611db3575f80fd5b50565b5f81519050611dc481611da0565b92915050565b5f60208284031215611ddf57611dde6117bb565b5b5f611dec84828501611db6565b91505092915050565b7f44657374696e6174696f6e20636861696e206e6f7420726567697374657265645f82015250565b5f611e296020836116ee565b9150611e3482611df5565b602082019050919050565b5f6020820190508181035f830152611e5681611e1d565b9050919050565b5f606082019050611e705f830186611b6b565b611e7d6020830185611b6b565b611e8a6040830184611d78565b949350505050565b7f5472616e73666572206661696c656400000000000000000000000000000000005f82015250565b5f611ec6600f836116ee565b9150611ed182611e92565b602082019050919050565b5f6020820190508181035f830152611ef381611eba565b9050919050565b5f81519050919050565b5f81905092915050565b8281835e5f83830152505050565b5f611f2682611efa565b611f308185611f04565b9350611f40818560208601611f0e565b80840191505092915050565b5f611f578284611f1c565b915081905092915050565b5f604082019050611f755f830185611b6b565b611f826020830184611d78565b9392505050565b7f5472616e7366657220746f20436869656656616c696461746f72206661696c655f8201527f6400000000000000000000000000000000000000000000000000000000000000602082015250565b5f611fe36021836116ee565b9150611fee82611f89565b604082019050919050565b5f6020820190508181035f83015261201081611fd7565b9050919050565b612020816117c3565b82525050565b5f61203082611efa565b61203a81856116ee565b935061204a818560208601611f0e565b6120538161195d565b840191505092915050565b5f6040820190506120715f830185612017565b81810360208301526120838184612026565b90509392505050565b7f4d7573742073656e6420455448000000000000000000000000000000000000005f82015250565b5f6120c0600d836116ee565b91506120cb8261208c565b602082019050919050565b5f6020820190508181035f8301526120ed816120b4565b9050919050565b5f815190506121028161192b565b92915050565b5f6020828403121561211d5761211c6117bb565b5b5f61212a848285016120f4565b91505092915050565b7f496e73756666696369656e742062616c616e63650000000000000000000000005f82015250565b5f6121676014836116ee565b915061217282612133565b602082019050919050565b5f6020820190508181035f8301526121948161215b565b9050919050565b7f496e76616c6964206164647265737300000000000000000000000000000000005f82015250565b5f6121cf600f836116ee565b91506121da8261219b565b602082019050919050565b5f6020820190508181035f8301526121fc816121c3565b9050919050565b7f41646472657373206973206e6f74206120636f6e7472616374000000000000005f82015250565b5f6122376019836116ee565b915061224282612203565b602082019050919050565b5f6020820190508181035f8301526122648161222b565b9050919050565b7f496e73756666696369656e7420574554482062616c616e6365000000000000005f82015250565b5f61229f6019836116ee565b91506122aa8261226b565b602082019050919050565b5f6020820190508181035f8301526122cc81612293565b9050919050565b7f2c000000000000000000000000000000000000000000000000000000000000005f82015250565b5f612307600183611f04565b9150612312826122d3565b600182019050919050565b5f6123288288611f1c565b9150612333826122fb565b915061233f8287611f1c565b915061234a826122fb565b91506123568286611f1c565b9150612361826122fb565b915061236d8285611f1c565b9150612378826122fb565b91506123848284611f1c565b91508190509695505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6123ca82611922565b91506123d583611922565b92508282039050818111156123ed576123ec612393565b5b92915050565b5f6123fd82611922565b915061240883611922565b925082820261241681611922565b9150828204841483151761242d5761242c612393565b5b5092915050565b5f8160011c9050919050565b5f808291508390505b60018511156124895780860481111561246557612464612393565b5b60018516156124745780820291505b808102905061248285612434565b9450612449565b94509492505050565b5f826124a1576001905061255c565b816124ae575f905061255c565b81600181146124c457600281146124ce576124fd565b600191505061255c565b60ff8411156124e0576124df612393565b5b8360020a9150848211156124f7576124f6612393565b5b5061255c565b5060208310610133831016604e8410600b84101617156125325782820a90508381111561252d5761252c612393565b5b61255c565b61253f8484846001612440565b9250905081840481111561255657612555612393565b5b81810290505b9392505050565b5f61256d82611922565b915061257883611922565b92506125a57fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8484612492565b905092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f6125e482611922565b91506125ef83611922565b9250826125ff576125fe6125ad565b5b828204905092915050565b5f60ff82169050919050565b5f6126208261260a565b915061262b8361260a565b92508261263b5761263a6125ad565b5b828204905092915050565b5f6126508261260a565b915061265b8361260a565b92508282026126698161260a565b915080821461267b5761267a612393565b5b5092915050565b5f61268c8261260a565b91506126978361260a565b9250828203905060ff8111156126b0576126af612393565b5b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f6126ed82611922565b91506126f883611922565b92508282019050808211156127105761270f612393565b5b92915050565b5f61272082611922565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361275257612751612393565b5b600182019050919050565b5f6127678261260a565b91506127728361260a565b9250828201905060ff81111561278b5761278a612393565b5b9291505056fea26469706673582212202bee3823fa9b27b04bac80a8cad53b0740dc067fef843f0af8e4dba64c03f56a64736f6c634300081a0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000062c517854f73515bca2179ef147ab45ef53b48bc00000000000000000000000092eed0282c6665c9bcc81605a13a5c3b1e4dc7f2000000000000000000000000039e2fb66102314ce7b64ce5ce3e5183bc94ad38000000000000000000000000bdfa3a2feb0673740dd6abe69a2db2c3b6459e17
-----Decoded View---------------
Arg [0] : _chiefValidator (address): 0x62C517854f73515bCa2179eF147Ab45EF53b48bC
Arg [1] : _initialOwner (address): 0x92eED0282c6665c9bcc81605A13a5C3b1E4Dc7F2
Arg [2] : _weth (address): 0x039e2fB66102314Ce7b64Ce5Ce3E5183bc94aD38
Arg [3] : _chainRouter (address): 0xBdFA3A2FeB0673740dD6abe69a2dB2C3B6459E17
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 00000000000000000000000062c517854f73515bca2179ef147ab45ef53b48bc
Arg [1] : 00000000000000000000000092eed0282c6665c9bcc81605a13a5c3b1e4dc7f2
Arg [2] : 000000000000000000000000039e2fb66102314ce7b64ce5ce3e5183bc94ad38
Arg [3] : 000000000000000000000000bdfa3a2feb0673740dd6abe69a2db2c3b6459e17
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 31 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.