0x75deb70b…6127sent to0xb2b01dec…c525·#21,239,099·view on Etherscan
data:application/vnd.facet.tx+json;rule=esip6,{"op":"call","data":{"to":"0x1673540243e793b0e77c038d4a88448eff524dce","function":"upgrade","args":{"newHash":"0xa46f3d0539f8556dc2f86b63e68249db6c1db193da387d780aaded983f4c7ae4","newSource":"pragma(:rubidity, \"1.0.0\")\ncontract(:ERC20, abstract: true) {\n event(:Transfer, { from: :address, to: :address, amount: :uint256 })\n event(:Approval, { owner: :address, spender: :address, amount: :uint256 })\n string(:public, :name)\n string(:public, :symbol)\n uint8(:public, :decimals)\n uint256(:public, :totalSupply)\n mapping(({ address: :uint256 }), :public, :balanceOf)\n mapping(({ address: mapping(address: :uint256) }), :public, :allowance)\n constructor(name: :string, symbol: :string, decimals: :uint8) {\n s.name=name\n s.symbol=symbol\n s.decimals=decimals\n }\n function(:approve, { spender: :address, amount: :uint256 }, :public, :virtual, returns: :bool) {\n s.allowance[msg.sender][spender] = amount\n emit(:Approval, owner: msg.sender, spender: spender, amount: amount)\n return true\n }\n function(:transfer, { to: :address, amount: :uint256 }, :public, :virtual, returns: :bool) {\n require(s.balanceOf[msg.sender] \u003e= amount, \"Insufficient balance\")\n s.balanceOf[msg.sender] -= amount\n s.balanceOf[to] += amount\n emit(:Transfer, from: msg.sender, to: to, amount: amount)\n return true\n }\n function(:transferFrom, { from: :address, to: :address, amount: :uint256 }, :public, :virtual, returns: :bool) {\n allowed = s.allowance[from][msg.sender]\n require(s.balanceOf[from] \u003e= amount, \"Insufficient balance\")\n require(allowed \u003e= amount, \"Insufficient allowance\")\n s.allowance[from][msg.sender] = allowed - amount\n s.balanceOf[from] -= amount\n s.balanceOf[to] += amount\n emit(:Transfer, from: from, to: to, amount: amount)\n return true\n }\n function(:_mint, { to: :address, amount: :uint256 }, :internal, :virtual) {\n s.totalSupply += amount\n s.balanceOf[to] += amount\n emit(:Transfer, from: address(0), to: to, amount: amount)\n }\n function(:_burn, { from: :address, amount: :uint256 }, :internal, :virtual) {\n require(s.balanceOf[from] \u003e= amount, \"Insufficient balance\")\n s.balanceOf[from] -= amount\n s.totalSupply -= amount\n emit(:Transfer, from: from, to: address(0), amount: amount)\n }\n}\ncontract(:FacetBuddy) {\n event(:CallOnBehalfOfUser, { onBehalfOf: :address, addressToCall: :address, calldata: :string, initialAmount: :uint256, finalAmount: :uint256, resultSuccess: :bool, resultData: :string })\n address(:public, :factory)\n address(:public, :erc20Bridge)\n address(:public, :forUser)\n bool(:locked)\n constructor(erc20Bridge: :address, forUser: :address) {\n s.factory=msg.sender\n s.erc20Bridge=erc20Bridge\n s.forUser=forUser\n }\n function(:_makeCall, { addressToCall: :address, calldata: :string, revertOnFailure: :bool }, :internal) {\n require(addressToCall != address(this), \"Cannot call self\")\n require(!s.locked, \"No reentrancy allowed\")\n s.locked=true\n initialBalance = _balance\n _approve(addressToCall, initialBalance)\n (success, data) = addressToCall.call(calldata)\n require(success || !revertOnFailure, \"Call failed: (#{calldata})\")\n _approve(addressToCall, 0)\n finalBalance = _balance\n if finalBalance \u003e 0\n _transfer(s.forUser, finalBalance)\n end\n s.locked=false\n emit(:CallOnBehalfOfUser, onBehalfOf: s.forUser, addressToCall: addressToCall, calldata: calldata, initialAmount: initialBalance, finalAmount: finalBalance, resultSuccess: success, resultData: data)\n }\n function(:callForUser, { amountToSpend: :uint256, addressToCall: :address, calldata: :string }, :public) {\n require(msg.sender == s.forUser || msg.sender == s.factory, \"Only the user or factory can callForUser\")\n ERC20(s.erc20Bridge).transferFrom(s.forUser, address(this), amountToSpend)\n _makeCall(addressToCall, calldata, true)\n }\n function(:callFromBridge, { addressToCall: :address, calldata: :string }, :public) {\n require(msg.sender == s.erc20Bridge, \"Only the bridge can callFromBridge\")\n _makeCall(addressToCall, calldata, false)\n }\n function(:_balance, :internal, :view, returns: :uint256) {\n ERC20(s.erc20Bridge).balanceOf(address(this))\n }\n function(:_approve, { spender: :address, amount: :uint256 }, :internal, returns: :bool) {\n ERC20(s.erc20Bridge).approve(spender, amount)\n }\n function(:_transfer, { to: :address, amount: :uint256 }, :internal, returns: :bool) {\n ERC20(s.erc20Bridge).transfer(to, amount)\n }\n}\ncontract(:Upgradeable, abstract: true) {\n address(:public, :upgradeAdmin)\n event(:ContractUpgraded, { oldHash: :bytes32, newHash: :bytes32 })\n event(:UpgradeAdminChanged, { newUpgradeAdmin: :address })\n constructor(upgradeAdmin: :address) {\n s.upgradeAdmin=upgradeAdmin\n }\n function(:setUpgradeAdmin, { newUpgradeAdmin: :address }, :public) {\n require(msg.sender == s.upgradeAdmin, \"NOT_AUTHORIZED\")\n s.upgradeAdmin=newUpgradeAdmin\n emit(:UpgradeAdminChanged, newUpgradeAdmin: newUpgradeAdmin)\n }\n function(:upgradeAndCall, { newHash: :bytes32, newSource: :string, migrationCalldata: :string }, :public) {\n upgrade(newHash: newHash, newSource: newSource)\n (success, data) = address(this).call(migrationCalldata)\n require(success, \"Migration failed\")\n }\n function(:upgrade, { newHash: :bytes32, newSource: :string }, :public) {\n currentHash = this.currentInitCodeHash\n require(msg.sender == s.upgradeAdmin, \"NOT_AUTHORIZED\")\n this.upgradeImplementation(newHash, newSource)\n emit(:ContractUpgraded, oldHash: currentHash, newHash: newHash)\n }\n}\ncontract(:FacetBuddyFactory, is: [:Upgradeable], upgradeable: true) {\n event(:BuddyCreated, { forUser: :address, buddy: :address })\n address(:public, :erc20Bridge)\n mapping(({ address: :address }), :public, :buddyForUser)\n mapping(({ address: :address }), :public, :userForBuddy)\n constructor(erc20Bridge: :address) {\n require(erc20Bridge != address(0), \"Invalid smart contract\")\n self.Upgradeable.constructor(upgradeAdmin: msg.sender)\n s.erc20Bridge=erc20Bridge\n }\n function(:findOrCreateBuddy, { forUser: :address }, :public, returns: :address) {\n existingBuddy = s.buddyForUser[forUser]\n if existingBuddy != address(0)\n return existingBuddy\n end\n salt = keccak256(abi.encodePacked(forUser))\n buddy = new(FacetBuddy(s.erc20Bridge, forUser, { salt: salt }))\n require(s.userForBuddy[buddy] == address(0), \"Buddy already exists for user\")\n s.buddyForUser[forUser] = buddy\n s.userForBuddy[buddy] = forUser\n emit(:BuddyCreated, forUser: forUser, buddy: buddy)\n return buddy\n }\n function(:callBuddyForUser, { amountToSpend: :uint256, addressToCall: :address, calldata: :string }, :public) {\n buddy = findOrCreateBuddy(msg.sender)\n FacetBuddy(buddy).callForUser(amountToSpend: amountToSpend, addressToCall: addressToCall, calldata: calldata)\n }\n function(:predictBuddyAddress, { forUser: :address }, :public, :view, returns: :address) {\n return create2_address(salt: keccak256(abi.encodePacked(forUser)), deployer: address(this), contract_type: \"FacetBuddy\")\n }\n}\ncontract(:Ownable, abstract: true) {\n address(:public, :owner)\n event(:OwnershipTransferred, { previousOwner: :address, newOwner: :address })\n constructor(owner: :address) {\n s.owner=owner\n }\n function(:transferOwnership, { newOwner: :address }, :public) {\n onlyOwner!\n previousOwner = s.owner\n s.owner=newOwner\n emit(:OwnershipTransferred, previousOwner: previousOwner, newOwner: newOwner)\n }\n function(:onlyOwner!, :internal) {\n require(msg.sender == s.owner, \"msg.sender is not the owner\")\n }\n}\ncontract(:Pausable, abstract: true) {\n bool(:public, :paused)\n event(:Paused, { account: :address })\n event(:Unpaused, { account: :address })\n constructor(initialPauseState: :bool) {\n s.paused=initialPauseState\n }\n function(:_pause, :internal) {\n s.paused=true\n emit(:Paused, account: msg.sender)\n }\n function(:_unpause, :internal) {\n s.paused=false\n emit(:Unpaused, account: msg.sender)\n }\n function(:whenPaused!, :internal) {\n require(s.paused, \"Contract is not paused\")\n }\n function(:whenNotPaused!, :internal) {\n require(!s.paused, \"Contract is paused\")\n }\n}\ncontract(:EtherBridge04, is: [:ERC20, :Upgradeable, :Ownable, :Pausable], upgradeable: true) {\n event(:BridgedIn, { to: :address, amount: :uint256 })\n event(:InitiateWithdrawal, { from: :address, amount: :uint256, withdrawalId: :bytes32 })\n event(:WithdrawalComplete, { to: :address, amount: :uint256, withdrawalId: :bytes32 })\n address(:public, :trustedSmartContract)\n address(:public, :facetBuddyFactory)\n mapping(({ bytes32: :uint256 }), :public, :withdrawalIdAmount)\n mapping(({ address: :bytes32 }), :public, :userWithdrawalId)\n constructor(name: :string, symbol: :string, trustedSmartContract: :address) {\n require(trustedSmartContract != address(0), \"Invalid smart contract\")\n self.ERC20.constructor(name: name, symbol: symbol, decimals: 18)\n self.Upgradeable.constructor(upgradeAdmin: msg.sender)\n self.Ownable.constructor(owner: msg.sender)\n s.trustedSmartContract=trustedSmartContract\n }\n function(:setFacetBuddyFactory, { facetBuddyFactory: :address }, :public) {\n onlyOwner!\n s.facetBuddyFactory=facetBuddyFactory\n nil\n }\n function(:bridgeIn, { to: :address, amount: :uint256 }, :public) {\n require(msg.sender == s.trustedSmartContract, \"Only the trusted smart contract can bridge in tokens\")\n _mint(to: to, amount: amount)\n emit(:BridgedIn, to: to, amount: amount)\n }\n function(:bridgeAndCall, { to: :address, amount: :uint256, addressToCall: :address, base64Calldata: :string }, :public) {\n if s.facetBuddyFactory == address(0)\n return bridgeIn(to: to, amount: amount)\n end\n buddy = FacetBuddyFactory(s.facetBuddyFactory).findOrCreateBuddy(to)\n bridgeIn(to: buddy, amount: amount)\n FacetBuddy(buddy).callFromBridge(addressToCall: addressToCall, calldata: base64Calldata.base64Decode)\n }\n function(:predictBuddyAddress, { forUser: :address }, :public, :view, returns: :address) {\n return FacetBuddyFactory(s.facetBuddyFactory).predictBuddyAddress(forUser)\n }\n function(:bridgeOut, { amount: :uint256 }, :public) {\n whenNotPaused!\n withdrawalId = tx.current_transaction_hash\n require(s.userWithdrawalId[msg.sender] == bytes32(0), \"Withdrawal pending\")\n require(s.withdrawalIdAmount[withdrawalId] == 0, \"Already bridged out\")\n require(amount \u003e 0, \"Invalid amount\")\n s.userWithdrawalId[msg.sender] = withdrawalId\n s.withdrawalIdAmount[withdrawalId] = amount\n _burn(from: msg.sender, amount: amount)\n emit(:InitiateWithdrawal, from: msg.sender, amount: amount, withdrawalId: withdrawalId)\n }\n function(:markWithdrawalComplete, { to: :address, withdrawalId: :bytes32 }, :public) {\n require(msg.sender == s.trustedSmartContract, \"Only the trusted smart contract can mark withdrawals as complete\")\n require(s.userWithdrawalId[to] == withdrawalId, \"Withdrawal id not found\")\n amount = s.withdrawalIdAmount[withdrawalId]\n s.withdrawalIdAmount[withdrawalId] = 0\n s.userWithdrawalId[to] = bytes32(0)\n emit(:WithdrawalComplete, to: to, amount: amount, withdrawalId: withdrawalId)\n }\n function(:pause, :public) {\n onlyOwner!\n _pause\n }\n function(:unpause, :public) {\n onlyOwner!\n _unpause\n }\n}\n"}}}