More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 823,088 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Fund And Run Mul... | 70647606 | 54 secs ago | IN | 5.62288779 POL | 0.01033485 | ||||
Call Bridge Call | 70647486 | 5 mins ago | IN | 0.43429287 POL | 0.01171527 | ||||
Fund And Run Mul... | 70647433 | 7 mins ago | IN | 0 POL | 0.00714417 | ||||
Execute With Tok... | 70647287 | 12 mins ago | IN | 0 POL | 0.00392816 | ||||
Express Execute ... | 70647201 | 15 mins ago | IN | 0 POL | 0.01468044 | ||||
Call Bridge Call | 70647167 | 16 mins ago | IN | 1.52690101 POL | 0.01167624 | ||||
Call Bridge Call | 70647059 | 20 mins ago | IN | 0.72472175 POL | 0.01166292 | ||||
Fund And Run Mul... | 70647055 | 20 mins ago | IN | 0 POL | 0.00714417 | ||||
Express Execute ... | 70647015 | 21 mins ago | IN | 0 POL | 0.0154544 | ||||
Express Execute ... | 70646977 | 23 mins ago | IN | 0 POL | 0.0164594 | ||||
Call Bridge Call | 70646858 | 27 mins ago | IN | 0.56991083 POL | 0.00278325 | ||||
Call Bridge Call | 70646848 | 27 mins ago | IN | 0.56991083 POL | 0.01407264 | ||||
Execute With Tok... | 70646792 | 29 mins ago | IN | 0 POL | 0.00507972 | ||||
Express Execute ... | 70646738 | 31 mins ago | IN | 0 POL | 0.01545728 | ||||
Execute With Tok... | 70646638 | 35 mins ago | IN | 0 POL | 0.00397143 | ||||
Express Execute ... | 70646569 | 37 mins ago | IN | 0 POL | 0.01453156 | ||||
Express Execute ... | 70646554 | 38 mins ago | IN | 0 POL | 0.01545704 | ||||
Execute With Tok... | 70646545 | 38 mins ago | IN | 0 POL | 0.00502095 | ||||
Execute With Tok... | 70646545 | 38 mins ago | IN | 0 POL | 0.00484867 | ||||
Express Execute ... | 70646488 | 40 mins ago | IN | 0 POL | 0.01450136 | ||||
Bridge Call | 70646401 | 43 mins ago | IN | 0.48964404 POL | 0.00505897 | ||||
Execute With Tok... | 70646189 | 51 mins ago | IN | 0 POL | 0.00514957 | ||||
Express Execute ... | 70646137 | 53 mins ago | IN | 0 POL | 0.01906356 | ||||
Fund And Run Mul... | 70646123 | 53 mins ago | IN | 1 POL | 0.00847071 | ||||
Call Bridge Call | 70645973 | 58 mins ago | IN | 0.52667776 POL | 0.00308919 |
Latest 25 internal transactions (View All)
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
70647606 | 54 secs ago | 5.62288779 POL | ||||
70647486 | 5 mins ago | 0.43429287 POL | ||||
70647389 | 8 mins ago | 5.97683377 POL | ||||
70647389 | 8 mins ago | 4.9995 POL | ||||
70647389 | 8 mins ago | 10.97633377 POL | ||||
70647167 | 16 mins ago | 0.52690101 POL | ||||
70647167 | 16 mins ago | 1 POL | ||||
70647063 | 20 mins ago | 0.43046331 POL | ||||
70647063 | 20 mins ago | 0.43046331 POL | ||||
70647059 | 20 mins ago | 0.62472175 POL | ||||
70647059 | 20 mins ago | 0.1 POL | ||||
70646848 | 27 mins ago | 0.56991083 POL | ||||
70646757 | 31 mins ago | 0.58214435 POL | ||||
70646757 | 31 mins ago | 0.58214435 POL | ||||
70646401 | 43 mins ago | 0.48964404 POL | ||||
70646305 | 47 mins ago | 0.5920914 POL | ||||
70646305 | 47 mins ago | 0.5920914 POL | ||||
70646123 | 53 mins ago | 1 POL | ||||
70645960 | 1 hrs ago | 0.51786886 POL | ||||
70645560 | 1 hr ago | 0.51611547 POL | ||||
70645395 | 1 hr ago | 0.58009426 POL | ||||
70645395 | 1 hr ago | 0.58009426 POL | ||||
70645265 | 1 hr ago | 0.57788249 POL | ||||
70645265 | 1 hr ago | 0.2 POL | ||||
70644713 | 1 hr ago | 0.57668443 POL |
Loading...
Loading
Contract Name:
SquidRouterProxy
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
Yes with 99999 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.17; import {Proxy} from "@axelar-network/axelar-gmp-sdk-solidity/contracts/upgradables/Proxy.sol"; contract SquidRouterProxy is Proxy { function contractId() internal pure override returns (bytes32 id) { id = keccak256("squid-router"); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.9; import './IUpgradable.sol'; // This should be owned by the microservice that is paying for gas. interface IAxelarGasService is IUpgradable { error NothingReceived(); error TransferFailed(); error InvalidAddress(); event GasPaidForContractCall( address indexed sourceAddress, string destinationChain, string destinationAddress, bytes32 indexed payloadHash, address gasToken, uint256 gasFeeAmount, address refundAddress ); event GasPaidForContractCallWithToken( address indexed sourceAddress, string destinationChain, string destinationAddress, bytes32 indexed payloadHash, string symbol, uint256 amount, address gasToken, uint256 gasFeeAmount, address refundAddress ); event NativeGasPaidForContractCall( address indexed sourceAddress, string destinationChain, string destinationAddress, bytes32 indexed payloadHash, uint256 gasFeeAmount, address refundAddress ); event NativeGasPaidForContractCallWithToken( address indexed sourceAddress, string destinationChain, string destinationAddress, bytes32 indexed payloadHash, string symbol, uint256 amount, uint256 gasFeeAmount, address refundAddress ); event GasAdded(bytes32 indexed txHash, uint256 indexed logIndex, address gasToken, uint256 gasFeeAmount, address refundAddress); event NativeGasAdded(bytes32 indexed txHash, uint256 indexed logIndex, uint256 gasFeeAmount, address refundAddress); // This is called on the source chain before calling the gateway to execute a remote contract. function payGasForContractCall( address sender, string calldata destinationChain, string calldata destinationAddress, bytes calldata payload, address gasToken, uint256 gasFeeAmount, address refundAddress ) external; // This is called on the source chain before calling the gateway to execute a remote contract. function payGasForContractCallWithToken( address sender, string calldata destinationChain, string calldata destinationAddress, bytes calldata payload, string calldata symbol, uint256 amount, address gasToken, uint256 gasFeeAmount, address refundAddress ) external; // This is called on the source chain before calling the gateway to execute a remote contract. function payNativeGasForContractCall( address sender, string calldata destinationChain, string calldata destinationAddress, bytes calldata payload, address refundAddress ) external payable; // This is called on the source chain before calling the gateway to execute a remote contract. function payNativeGasForContractCallWithToken( address sender, string calldata destinationChain, string calldata destinationAddress, bytes calldata payload, string calldata symbol, uint256 amount, address refundAddress ) external payable; function addGas( bytes32 txHash, uint256 txIndex, address gasToken, uint256 gasFeeAmount, address refundAddress ) external; function addNativeGas( bytes32 txHash, uint256 logIndex, address refundAddress ) external payable; function collectFees(address payable receiver, address[] calldata tokens) external; function refund( address payable receiver, address token, uint256 amount ) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.9; // General interface for upgradable contracts interface IUpgradable { error NotOwner(); error InvalidOwner(); error InvalidCodeHash(); error InvalidImplementation(); error SetupFailed(); error NotProxy(); event Upgraded(address indexed newImplementation); event OwnershipTransferred(address indexed newOwner); // Get current owner function owner() external view returns (address); function contractId() external pure returns (bytes32); function implementation() external view returns (address); function upgrade( address newImplementation, bytes32 newImplementationCodeHash, bytes calldata params ) external; function setup(bytes calldata data) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import { IAxelarGateway } from '../interfaces/IAxelarGateway.sol'; import { IERC20 } from '../interfaces/IERC20.sol'; import { IAxelarForecallable } from '../interfaces/IAxelarForecallable.sol'; contract AxelarForecallable is IAxelarForecallable { IAxelarGateway public immutable gateway; //keccak256('forecallers'); uint256 public constant FORECALLERS_SALT = 0xdb79ee324babd8834c3c1a1a2739c004fce73b812ac9f637241ff47b19e4b71f; constructor(address gateway_) { if (gateway_ == address(0)) revert InvalidAddress(); gateway = IAxelarGateway(gateway_); } function getForecaller( string calldata sourceChain, string calldata sourceAddress, bytes calldata payload ) public view override returns (address forecaller) { bytes32 pos = keccak256(abi.encode(sourceChain, sourceAddress, payload, FORECALLERS_SALT)); // solhint-disable-next-line no-inline-assembly assembly { forecaller := sload(pos) } } function _setForecaller( string calldata sourceChain, string calldata sourceAddress, bytes calldata payload, address forecaller ) internal { bytes32 pos = keccak256(abi.encode(sourceChain, sourceAddress, payload, FORECALLERS_SALT)); // solhint-disable-next-line no-inline-assembly assembly { sstore(pos, forecaller) } } function forecall( string calldata sourceChain, string calldata sourceAddress, bytes calldata payload ) external { _checkForecall(sourceChain, sourceAddress, payload, msg.sender); if (getForecaller(sourceChain, sourceAddress, payload) != address(0)) revert AlreadyForecalled(); _setForecaller(sourceChain, sourceAddress, payload, msg.sender); _execute(sourceChain, sourceAddress, payload); } function execute( bytes32 commandId, string calldata sourceChain, string calldata sourceAddress, bytes calldata payload ) external override { bytes32 payloadHash = keccak256(payload); if (!gateway.validateContractCall(commandId, sourceChain, sourceAddress, payloadHash)) revert NotApprovedByGateway(); address forecaller = getForecaller(sourceChain, sourceAddress, payload); if (forecaller != address(0)) { _setForecaller(sourceChain, sourceAddress, payload, address(0)); } else { _execute(sourceChain, sourceAddress, payload); } } function getForecallerWithToken( string calldata sourceChain, string calldata sourceAddress, bytes calldata payload, string calldata symbol, uint256 amount ) public view override returns (address forecaller) { bytes32 pos = keccak256(abi.encode(sourceChain, sourceAddress, payload, symbol, amount, FORECALLERS_SALT)); // solhint-disable-next-line no-inline-assembly assembly { forecaller := sload(pos) } } function _setForecallerWithToken( string calldata sourceChain, string calldata sourceAddress, bytes calldata payload, string calldata symbol, uint256 amount, address forecaller ) internal { bytes32 pos = keccak256(abi.encode(sourceChain, sourceAddress, payload, symbol, amount, FORECALLERS_SALT)); // solhint-disable-next-line no-inline-assembly assembly { sstore(pos, forecaller) } } function forecallWithToken( string calldata sourceChain, string calldata sourceAddress, bytes calldata payload, string calldata tokenSymbol, uint256 amount ) external override { address token = gateway.tokenAddresses(tokenSymbol); uint256 amountPost = amountPostFee(amount, payload); _safeTransferFrom(token, msg.sender, amountPost); _checkForecallWithToken(sourceChain, sourceAddress, payload, tokenSymbol, amount, msg.sender); if (getForecallerWithToken(sourceChain, sourceAddress, payload, tokenSymbol, amount) != address(0)) revert AlreadyForecalled(); _setForecallerWithToken(sourceChain, sourceAddress, payload, tokenSymbol, amount, msg.sender); _executeWithToken(sourceChain, sourceAddress, payload, tokenSymbol, amountPost); } function executeWithToken( bytes32 commandId, string calldata sourceChain, string calldata sourceAddress, bytes calldata payload, string calldata tokenSymbol, uint256 amount ) external override { bytes32 payloadHash = keccak256(payload); if ( !gateway.validateContractCallAndMint( commandId, sourceChain, sourceAddress, payloadHash, tokenSymbol, amount ) ) revert NotApprovedByGateway(); address forecaller = getForecallerWithToken(sourceChain, sourceAddress, payload, tokenSymbol, amount); if (forecaller != address(0)) { _setForecallerWithToken(sourceChain, sourceAddress, payload, tokenSymbol, amount, address(0)); address token = gateway.tokenAddresses(tokenSymbol); _safeTransfer(token, forecaller, amount); } else { _executeWithToken(sourceChain, sourceAddress, payload, tokenSymbol, amount); } } function _execute( string calldata sourceChain, string calldata sourceAddress, bytes calldata payload ) internal virtual {} function _executeWithToken( string calldata sourceChain, string calldata sourceAddress, bytes calldata payload, string calldata tokenSymbol, uint256 amount ) internal virtual {} // Override this to keep a fee. function amountPostFee( uint256 amount, bytes calldata /*payload*/ ) public virtual override returns (uint256) { return amount; } // Override this and revert if you want to only allow certain people/calls to be able to forecall. function _checkForecall( string calldata sourceChain, string calldata sourceAddress, bytes calldata payload, address forecaller ) internal virtual {} // Override this and revert if you want to only allow certain people/calls to be able to forecall. function _checkForecallWithToken( string calldata sourceChain, string calldata sourceAddress, bytes calldata payload, string calldata tokenSymbol, uint256 amount, address forecaller ) internal virtual {} function _safeTransfer( address tokenAddress, address receiver, uint256 amount ) internal { (bool success, bytes memory returnData) = tokenAddress.call( abi.encodeWithSelector(IERC20.transfer.selector, receiver, amount) ); bool transferred = success && (returnData.length == uint256(0) || abi.decode(returnData, (bool))); if (!transferred || tokenAddress.code.length == 0) revert TransferFailed(); } function _safeTransferFrom( address tokenAddress, address from, uint256 amount ) internal { (bool success, bytes memory returnData) = tokenAddress.call( abi.encodeWithSelector(IERC20.transferFrom.selector, from, address(this), amount) ); bool transferred = success && (returnData.length == uint256(0) || abi.decode(returnData, (bool))); if (!transferred || tokenAddress.code.length == 0) revert TransferFailed(); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import { IAxelarGateway } from '../interfaces/IAxelarGateway.sol'; interface IAxelarExecutable { error InvalidAddress(); error NotApprovedByGateway(); function gateway() external view returns (IAxelarGateway); function execute( bytes32 commandId, string calldata sourceChain, string calldata sourceAddress, bytes calldata payload ) external; function executeWithToken( bytes32 commandId, string calldata sourceChain, string calldata sourceAddress, bytes calldata payload, string calldata tokenSymbol, uint256 amount ) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import { IAxelarExecutable } from '../interfaces/IAxelarExecutable.sol'; interface IAxelarForecallable is IAxelarExecutable { error AlreadyForecalled(); error TransferFailed(); function forecall( string calldata sourceChain, string calldata sourceAddress, bytes calldata payload ) external; function forecallWithToken( string calldata sourceChain, string calldata sourceAddress, bytes calldata payload, string calldata tokenSymbol, uint256 amount ) external; function getForecaller( string calldata sourceChain, string calldata sourceAddress, bytes calldata payload ) external returns (address forecaller); function getForecallerWithToken( string calldata sourceChain, string calldata sourceAddress, bytes calldata payload, string calldata symbol, uint256 amount ) external returns (address forecaller); function amountPostFee(uint256 amount, bytes calldata payload) external returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IAxelarGateway { /**********\ |* Errors *| \**********/ error NotSelf(); error NotProxy(); error InvalidCodeHash(); error SetupFailed(); error InvalidAuthModule(); error InvalidTokenDeployer(); error InvalidAmount(); error InvalidChainId(); error InvalidCommands(); error TokenDoesNotExist(string symbol); error TokenAlreadyExists(string symbol); error TokenDeployFailed(string symbol); error TokenContractDoesNotExist(address token); error BurnFailed(string symbol); error MintFailed(string symbol); error InvalidSetMintLimitsParams(); error ExceedMintLimit(string symbol); /**********\ |* Events *| \**********/ event TokenSent( address indexed sender, string destinationChain, string destinationAddress, string symbol, uint256 amount ); event ContractCall( address indexed sender, string destinationChain, string destinationContractAddress, bytes32 indexed payloadHash, bytes payload ); event ContractCallWithToken( address indexed sender, string destinationChain, string destinationContractAddress, bytes32 indexed payloadHash, bytes payload, string symbol, uint256 amount ); event Executed(bytes32 indexed commandId); event TokenDeployed(string symbol, address tokenAddresses); event ContractCallApproved( bytes32 indexed commandId, string sourceChain, string sourceAddress, address indexed contractAddress, bytes32 indexed payloadHash, bytes32 sourceTxHash, uint256 sourceEventIndex ); event ContractCallApprovedWithMint( bytes32 indexed commandId, string sourceChain, string sourceAddress, address indexed contractAddress, bytes32 indexed payloadHash, string symbol, uint256 amount, bytes32 sourceTxHash, uint256 sourceEventIndex ); event TokenMintLimitUpdated(string symbol, uint256 limit); event OperatorshipTransferred(bytes newOperatorsData); event Upgraded(address indexed implementation); /********************\ |* Public Functions *| \********************/ function sendToken( string calldata destinationChain, string calldata destinationAddress, string calldata symbol, uint256 amount ) external; function callContract( string calldata destinationChain, string calldata contractAddress, bytes calldata payload ) external; function callContractWithToken( string calldata destinationChain, string calldata contractAddress, bytes calldata payload, string calldata symbol, uint256 amount ) external; function isContractCallApproved( bytes32 commandId, string calldata sourceChain, string calldata sourceAddress, address contractAddress, bytes32 payloadHash ) external view returns (bool); function isContractCallAndMintApproved( bytes32 commandId, string calldata sourceChain, string calldata sourceAddress, address contractAddress, bytes32 payloadHash, string calldata symbol, uint256 amount ) external view returns (bool); function validateContractCall( bytes32 commandId, string calldata sourceChain, string calldata sourceAddress, bytes32 payloadHash ) external returns (bool); function validateContractCallAndMint( bytes32 commandId, string calldata sourceChain, string calldata sourceAddress, bytes32 payloadHash, string calldata symbol, uint256 amount ) external returns (bool); /***********\ |* Getters *| \***********/ function authModule() external view returns (address); function tokenDeployer() external view returns (address); function tokenMintLimit(string memory symbol) external view returns (uint256); function tokenMintAmount(string memory symbol) external view returns (uint256); function allTokensFrozen() external view returns (bool); function implementation() external view returns (address); function tokenAddresses(string memory symbol) external view returns (address); function tokenFrozen(string memory symbol) external view returns (bool); function isCommandExecuted(bytes32 commandId) external view returns (bool); function adminEpoch() external view returns (uint256); function adminThreshold(uint256 epoch) external view returns (uint256); function admins(uint256 epoch) external view returns (address[] memory); /*******************\ |* Admin Functions *| \*******************/ function setTokenMintLimits(string[] calldata symbols, uint256[] calldata limits) external; function upgrade( address newImplementation, bytes32 newImplementationCodeHash, bytes calldata setupParams ) external; /**********************\ |* External Functions *| \**********************/ function setup(bytes calldata params) external; function execute(bytes calldata input) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { error InvalidAccount(); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address sender, address recipient, uint256 amount ) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; // General interface for upgradable contracts interface IUpgradable { error NotOwner(); error InvalidOwner(); error InvalidCodeHash(); error InvalidImplementation(); error SetupFailed(); error NotProxy(); event Upgraded(address indexed newImplementation); event OwnershipTransferred(address indexed newOwner); // Get current owner function owner() external view returns (address); function contractId() external pure returns (bytes32); function upgrade( address newImplementation, bytes32 newImplementationCodeHash, bytes calldata params ) external; function setup(bytes calldata data) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; library StringToAddress { function toAddress(string memory _a) internal pure returns (address) { bytes memory tmp = bytes(_a); if (tmp.length != 42) return address(0); uint160 iaddr = 0; uint8 b; for (uint256 i = 2; i < 42; i++) { b = uint8(tmp[i]); if ((b >= 97) && (b <= 102)) b -= 87; else if ((b >= 65) && (b <= 70)) b -= 55; else if ((b >= 48) && (b <= 57)) b -= 48; else return address(0); iaddr |= uint160(uint256(b) << ((41 - i) << 2)); } return address(iaddr); } } library AddressToString { function toString(address a) internal pure returns (string memory) { bytes memory data = abi.encodePacked(a); bytes memory characters = '0123456789abcdef'; bytes memory byteString = new bytes(2 + data.length * 2); byteString[0] = '0'; byteString[1] = 'x'; for (uint256 i; i < data.length; ++i) { byteString[2 + i * 2] = characters[uint256(uint8(data[i] >> 4))]; byteString[3 + i * 2] = characters[uint256(uint8(data[i] & 0x0f))]; } return string(byteString); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import { IUpgradable } from '../interfaces/IUpgradable.sol'; contract Proxy { error InvalidImplementation(); error SetupFailed(); error EtherNotAccepted(); error NotOwner(); error AlreadyInitialized(); // bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1) bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; // keccak256('owner') bytes32 internal constant _OWNER_SLOT = 0x02016836a56b71f0d02689e69e326f4f4c1b9057164ef592671cf0d37c8040c0; constructor() { // solhint-disable-next-line no-inline-assembly assembly { sstore(_OWNER_SLOT, caller()) } } function init( address implementationAddress, address newOwner, bytes memory params ) external { address owner; // solhint-disable-next-line no-inline-assembly assembly { owner := sload(_OWNER_SLOT) } if (msg.sender != owner) revert NotOwner(); if (implementation() != address(0)) revert AlreadyInitialized(); if (IUpgradable(implementationAddress).contractId() != contractId()) revert InvalidImplementation(); // solhint-disable-next-line no-inline-assembly assembly { sstore(_IMPLEMENTATION_SLOT, implementationAddress) sstore(_OWNER_SLOT, newOwner) } // solhint-disable-next-line avoid-low-level-calls (bool success, ) = implementationAddress.delegatecall( //0x9ded06df is the setup selector. abi.encodeWithSelector(0x9ded06df, params) ); if (!success) revert SetupFailed(); } // solhint-disable-next-line no-empty-blocks function contractId() internal pure virtual returns (bytes32) {} function implementation() public view returns (address implementation_) { // solhint-disable-next-line no-inline-assembly assembly { implementation_ := sload(_IMPLEMENTATION_SLOT) } } // solhint-disable-next-line no-empty-blocks function setup(bytes calldata data) public {} // solhint-disable-next-line no-complex-fallback fallback() external payable { address implementaion_ = implementation(); // solhint-disable-next-line no-inline-assembly assembly { calldatacopy(0, 0, calldatasize()) let result := delegatecall(gas(), implementaion_, 0, calldatasize(), 0, 0) returndatacopy(0, 0, returndatasize()) switch result case 0 { revert(0, returndatasize()) } default { return(0, returndatasize()) } } } receive() external payable virtual { revert EtherNotAccepted(); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import '../interfaces/IUpgradable.sol'; abstract contract Upgradable is IUpgradable { // bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1) bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; // keccak256('owner') bytes32 internal constant _OWNER_SLOT = 0x02016836a56b71f0d02689e69e326f4f4c1b9057164ef592671cf0d37c8040c0; modifier onlyOwner() { if (owner() != msg.sender) revert NotOwner(); _; } function owner() public view returns (address owner_) { // solhint-disable-next-line no-inline-assembly assembly { owner_ := sload(_OWNER_SLOT) } } function transferOwnership(address newOwner) external virtual onlyOwner { if (newOwner == address(0)) revert InvalidOwner(); emit OwnershipTransferred(newOwner); // solhint-disable-next-line no-inline-assembly assembly { sstore(_OWNER_SLOT, newOwner) } } function implementation() public view returns (address implementation_) { // solhint-disable-next-line no-inline-assembly assembly { implementation_ := sload(_IMPLEMENTATION_SLOT) } } function upgrade( address newImplementation, bytes32 newImplementationCodeHash, bytes calldata params ) external override onlyOwner { if (IUpgradable(newImplementation).contractId() != IUpgradable(this).contractId()) revert InvalidImplementation(); if (newImplementationCodeHash != newImplementation.codehash) revert InvalidCodeHash(); if (params.length > 0) { // solhint-disable-next-line avoid-low-level-calls (bool success, ) = newImplementation.delegatecall(abi.encodeWithSelector(this.setup.selector, params)); if (!success) revert SetupFailed(); } emit Upgraded(newImplementation); // solhint-disable-next-line no-inline-assembly assembly { sstore(_IMPLEMENTATION_SLOT, newImplementation) } } function setup(bytes calldata data) external override { // Prevent setup from being called on the implementation if (implementation() == address(0)) revert NotProxy(); _setup(data); } // solhint-disable-next-line no-empty-blocks function _setup(bytes calldata data) internal virtual {} }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); }
pragma solidity >=0.6.2; interface IPangolinRouter { function factory() external pure returns (address); function WAVAX() external pure returns (address); function addLiquidity( address tokenA, address tokenB, uint amountADesired, uint amountBDesired, uint amountAMin, uint amountBMin, address to, uint deadline ) external returns (uint amountA, uint amountB, uint liquidity); function addLiquidityAVAX( address token, uint amountTokenDesired, uint amountTokenMin, uint amountAVAXMin, address to, uint deadline ) external payable returns (uint amountToken, uint amountAVAX, uint liquidity); function removeLiquidity( address tokenA, address tokenB, uint liquidity, uint amountAMin, uint amountBMin, address to, uint deadline ) external returns (uint amountA, uint amountB); function removeLiquidityAVAX( address token, uint liquidity, uint amountTokenMin, uint amountAVAXMin, address to, uint deadline ) external returns (uint amountToken, uint amountAVAX); function removeLiquidityWithPermit( address tokenA, address tokenB, uint liquidity, uint amountAMin, uint amountBMin, address to, uint deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint amountA, uint amountB); function removeLiquidityAVAXWithPermit( address token, uint liquidity, uint amountTokenMin, uint amountAVAXMin, address to, uint deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint amountToken, uint amountAVAX); function swapExactTokensForTokens( uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline ) external returns (uint[] memory amounts); function swapTokensForExactTokens( uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline ) external returns (uint[] memory amounts); function swapExactAVAXForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline) external payable returns (uint[] memory amounts); function swapTokensForExactAVAX(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline) external returns (uint[] memory amounts); function swapExactTokensForAVAX(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline) external returns (uint[] memory amounts); function swapAVAXForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline) external payable returns (uint[] memory amounts); function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB); function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut); function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn); function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts); function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts); function removeLiquidityAVAXSupportingFeeOnTransferTokens( address token, uint liquidity, uint amountTokenMin, uint amountAVAXMin, address to, uint deadline ) external returns (uint amountAVAX); function removeLiquidityAVAXWithPermitSupportingFeeOnTransferTokens( address token, uint liquidity, uint amountTokenMin, uint amountAVAXMin, address to, uint deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint amountAVAX); function swapExactTokensForTokensSupportingFeeOnTransferTokens( uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline ) external; function swapExactAVAXForTokensSupportingFeeOnTransferTokens( uint amountOutMin, address[] calldata path, address to, uint deadline ) external payable; function swapExactTokensForAVAXSupportingFeeOnTransferTokens( uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline ) external; }
// SPDX-License-Identifier: UNLICENSED pragma solidity >0.0.0; import '@pangolindex/exchange-contracts/contracts/pangolin-periphery/interfaces/IPangolinRouter.sol';
// SPDX-License-Identifier: MIT pragma solidity 0.8.17; interface IRoledPausable { event PauserProposed(address indexed currentPauser, address indexed pendingPauser); event PauserUpdated(address indexed pendingPauser); event Paused(); event Unpaused(); error ContractIsPaused(); error NotPauser(); error NotPendingPauser(); function updatePauser(address _newPauser) external; function acceptPauser() external; function pause() external; function unpause() external; function paused() external view returns (bool value); function pauser() external view returns (address value); function pendingPauser() external view returns (address value); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.17; interface ISquidFeeCollector { event FeeCollected(address token, address integrator, uint256 squidFee, uint256 integratorFee); event FeeWithdrawn(address token, address account, uint256 amount); error TransferFailed(); error ExcessiveIntegratorFee(); function collectFee( address token, uint256 amountToTax, address integratorAddress, uint256 integratorFee ) external; function withdrawFee(address token) external; function getBalance(address token, address account) external view returns (uint256 accountBalance); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.17; interface ISquidMulticall { enum CallType { Default, FullTokenBalance, FullNativeBalance, CollectTokenBalance } struct Call { CallType callType; address target; uint256 value; bytes callData; bytes payload; } error AlreadyRunning(); error CallFailed(uint256 callPosition, bytes reason); function run(Call[] calldata calls) external payable; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.17; import {ISquidMulticall} from "./ISquidMulticall.sol"; interface ISquidRouter { event CrossMulticallExecuted(bytes32 indexed payloadHash); event CrossMulticallFailed(bytes32 indexed payloadHash, bytes reason, address indexed refundRecipient); function bridgeCall( string calldata destinationChain, string calldata bridgedTokenSymbol, uint256 amount, ISquidMulticall.Call[] calldata calls, address refundRecipient, bool forecallEnabled ) external payable; function callBridge( address token, uint256 amount, string calldata destinationChain, string calldata destinationAddress, string calldata bridgedTokenSymbol, ISquidMulticall.Call[] calldata calls ) external payable; function callBridgeCall( address token, uint256 amount, string calldata destinationChain, string calldata bridgedTokenSymbol, ISquidMulticall.Call[] calldata sourceCalls, ISquidMulticall.Call[] calldata destinationCalls, address refundRecipient, bool forecallEnabled ) external payable; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; library StorageSlot { function setUint256(bytes32 slot, uint256 value) internal { assembly { sstore(slot, value) } } function getUint256(bytes32 slot) internal view returns (uint256 value) { assembly { value := sload(slot) } } function setAddress(bytes32 slot, address value) internal { assembly { sstore(slot, value) } } function getAddress(bytes32 slot) internal view returns (address value) { assembly { value := sload(slot) } } function setBool(bytes32 slot, bool value) internal { assembly { sstore(slot, value) } } function getBool(bytes32 slot) internal view returns (bool value) { assembly { value := sload(slot) } } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.17; import {IRoledPausable} from "./interfaces/IRoledPausable.sol"; import {StorageSlot} from "./libraries/StorageSlot.sol"; abstract contract RoledPausable is IRoledPausable { using StorageSlot for bytes32; bytes32 internal constant PAUSED_SLOT = keccak256("RoledPausable.paused"); bytes32 internal constant PAUSER_SLOT = keccak256("RoledPausable.pauser"); bytes32 internal constant PENDING_PAUSER_SLOT = keccak256("RoledPausable.pendingPauser"); modifier whenNotPaused() { if (paused()) revert ContractIsPaused(); _; } modifier onlyPauser() { if (msg.sender != pauser()) revert NotPauser(); _; } constructor() { _setPauser(msg.sender); } function updatePauser(address newPauser) external onlyPauser { PENDING_PAUSER_SLOT.setAddress(newPauser); emit PauserProposed(msg.sender, newPauser); } function acceptPauser() external { if (msg.sender != pendingPauser()) revert NotPendingPauser(); _setPauser(msg.sender); PENDING_PAUSER_SLOT.setAddress(address(0)); } function pause() external virtual onlyPauser { PAUSED_SLOT.setBool(true); emit Paused(); } function unpause() external virtual onlyPauser { PAUSED_SLOT.setBool(false); emit Unpaused(); } function pauser() public view returns (address value) { value = PAUSER_SLOT.getAddress(); } function paused() public view returns (bool value) { value = PAUSED_SLOT.getBool(); } function pendingPauser() public view returns (address value) { value = PENDING_PAUSER_SLOT.getAddress(); } function _setPauser(address _pauser) internal { PAUSER_SLOT.setAddress(_pauser); emit PauserUpdated(_pauser); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.17; import {Upgradable} from "@axelar-network/axelar-gmp-sdk-solidity/contracts/upgradables/Upgradable.sol"; import {ISquidFeeCollector} from "./interfaces/ISquidFeeCollector.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; contract SquidFeeCollector is ISquidFeeCollector, Upgradable { bytes32 private constant BALANCES_PREFIX = keccak256("SquidFeeCollector.balances"); bytes32 private constant SPECIFIC_FEES_PREFIX = keccak256("SquidFeeCollector.specificFees"); address public immutable squidTeam; // Value expected with 2 decimals /// eg. 825 is 8.25% uint256 public immutable squidDefaultFee; error ZeroAddressProvided(); constructor(address _squidTeam, uint256 _squidDefaultFee) { if (_squidTeam == address(0)) revert ZeroAddressProvided(); squidTeam = _squidTeam; squidDefaultFee = _squidDefaultFee; } /// @param integratorFee Value expected with 2 decimals /// eg. 825 is 8.25% function collectFee( address token, uint256 amountToTax, address integratorAddress, uint256 integratorFee ) external { if (integratorFee > 1000) revert ExcessiveIntegratorFee(); uint256 specificFee = getSpecificFee(integratorAddress); uint256 squidFee = specificFee == 0 ? squidDefaultFee : specificFee; uint256 baseFeeAmount = (amountToTax * integratorFee) / 10000; uint256 squidFeeAmount = (baseFeeAmount * squidFee) / 10000; uint256 integratorFeeAmount = baseFeeAmount - squidFeeAmount; _safeTransferFrom(token, msg.sender, baseFeeAmount); _setBalance(token, squidTeam, getBalance(token, squidTeam) + squidFeeAmount); _setBalance(token, integratorAddress, getBalance(token, integratorAddress) + integratorFeeAmount); emit FeeCollected(token, integratorAddress, squidFeeAmount, integratorFeeAmount); } function withdrawFee(address token) external { uint256 balance = getBalance(token, msg.sender); _setBalance(token, msg.sender, 0); _safeTransfer(token, msg.sender, balance); emit FeeWithdrawn(token, msg.sender, balance); } function setSpecificFee(address integrator, uint256 fee) external onlyOwner { bytes32 slot = _computeSpecificFeeSlot(integrator); assembly { sstore(slot, fee) } } function getBalance(address token, address account) public view returns (uint256 value) { bytes32 slot = _computeBalanceSlot(token, account); assembly { value := sload(slot) } } function getSpecificFee(address integrator) public view returns (uint256 value) { bytes32 slot = _computeSpecificFeeSlot(integrator); assembly { value := sload(slot) } } function contractId() external pure returns (bytes32 id) { id = keccak256("squid-fee-collector"); } function _setBalance( address token, address account, uint256 amount ) private { bytes32 slot = _computeBalanceSlot(token, account); assembly { sstore(slot, amount) } } function _computeBalanceSlot(address token, address account) private pure returns (bytes32 slot) { slot = keccak256(abi.encodePacked(BALANCES_PREFIX, token, account)); } function _computeSpecificFeeSlot(address integrator) private pure returns (bytes32 slot) { slot = keccak256(abi.encodePacked(SPECIFIC_FEES_PREFIX, integrator)); } function _safeTransferFrom( address token, address from, uint256 amount ) internal { (bool success, bytes memory returnData) = token.call( abi.encodeWithSelector(IERC20.transferFrom.selector, from, address(this), amount) ); bool transferred = success && (returnData.length == uint256(0) || abi.decode(returnData, (bool))); if (!transferred || token.code.length == 0) revert TransferFailed(); } function _safeTransfer( address token, address to, uint256 amount ) internal { (bool success, bytes memory returnData) = token.call( abi.encodeWithSelector(IERC20.transfer.selector, to, amount) ); bool transferred = success && (returnData.length == uint256(0) || abi.decode(returnData, (bool))); if (!transferred || token.code.length == 0) revert TransferFailed(); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.17; import {Proxy} from "@axelar-network/axelar-gmp-sdk-solidity/contracts/upgradables/Proxy.sol"; contract SquidFeeCollectorProxy is Proxy { function contractId() internal pure override returns (bytes32 id) { id = keccak256("squid-fee-collector"); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.17; import {ISquidMulticall} from "./interfaces/ISquidMulticall.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; contract SquidMulticall is ISquidMulticall { bool private isRunning; error TransferFailed(); function run(Call[] calldata calls) external payable { // Prevents reentrancy if (isRunning) revert AlreadyRunning(); isRunning = true; for (uint256 i = 0; i < calls.length; i++) { Call memory call = calls[i]; if (call.callType == CallType.FullTokenBalance) { (address token, uint256 amountParameterPosition) = abi.decode(call.payload, (address, uint256)); uint256 amount = IERC20(token).balanceOf(address(this)); _setCallDataParameter(call.callData, amountParameterPosition, amount); } else if (call.callType == CallType.FullNativeBalance) { call.value = address(this).balance; } else if (call.callType == CallType.CollectTokenBalance) { address token = abi.decode(call.payload, (address)); _safeTransferFrom(token, msg.sender, IERC20(token).balanceOf(msg.sender)); continue; } (bool success, bytes memory data) = call.target.call{value: call.value}(call.callData); if (!success) revert CallFailed(i, data); } isRunning = false; } function _safeTransferFrom( address token, address from, uint256 amount ) internal { (bool success, bytes memory returnData) = token.call( abi.encodeWithSelector(IERC20.transferFrom.selector, from, address(this), amount) ); bool transferred = success && (returnData.length == uint256(0) || abi.decode(returnData, (bool))); if (!transferred || token.code.length == 0) revert TransferFailed(); } function _setCallDataParameter( bytes memory callData, uint256 parameterPosition, uint256 value ) private pure { assembly { // 36 bytes shift because 32 for prefix + 4 for selector mstore(add(callData, add(36, mul(parameterPosition, 32))), value) } } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.17; import {ISquidRouter} from "./interfaces/ISquidRouter.sol"; import {ISquidMulticall} from "./interfaces/ISquidMulticall.sol"; import {AxelarForecallable} from "@axelar-network/axelar-gmp-sdk-solidity/contracts/executables/AxelarForecallable.sol"; import {IAxelarGasService} from "@axelar-network/axelar-cgp-solidity/contracts/interfaces/IAxelarGasService.sol"; import {IAxelarGateway} from "@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IAxelarGateway.sol"; import {AddressToString} from "@axelar-network/axelar-gmp-sdk-solidity/contracts/StringAddressUtils.sol"; import {Upgradable} from "@axelar-network/axelar-gmp-sdk-solidity/contracts/upgradables/Upgradable.sol"; import {RoledPausable} from "./RoledPausable.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; contract SquidRouter is ISquidRouter, AxelarForecallable, Upgradable, RoledPausable { using AddressToString for address; IAxelarGasService private immutable gasService; IAxelarGasService private immutable forecallGasService; ISquidMulticall private immutable squidMulticall; error ZeroAddressProvided(); constructor( address _gateway, address _gasService, address _forecallGasService, address _multicall ) AxelarForecallable(_gateway) { if ( _gateway == address(0) || _gasService == address(0) || _forecallGasService == address(0) || _multicall == address(0) ) revert ZeroAddressProvided(); gasService = IAxelarGasService(_gasService); forecallGasService = IAxelarGasService(_forecallGasService); squidMulticall = ISquidMulticall(_multicall); } function bridgeCall( string calldata destinationChain, string calldata bridgedTokenSymbol, uint256 amount, ISquidMulticall.Call[] calldata calls, address refundRecipient, bool enableForecall ) external payable whenNotPaused { address bridgedTokenAddress = gateway.tokenAddresses(bridgedTokenSymbol); _safeTransferFrom(bridgedTokenAddress, msg.sender, amount); _bridgeCall(destinationChain, bridgedTokenSymbol, bridgedTokenAddress, calls, refundRecipient, enableForecall); } function callBridge( address token, uint256 amount, string calldata destinationChain, string calldata destinationAddress, string calldata bridgedTokenSymbol, ISquidMulticall.Call[] calldata calls ) external payable whenNotPaused { fundAndRunMulticall(token, amount, calls); address bridgedTokenAddress = gateway.tokenAddresses(bridgedTokenSymbol); uint256 bridgedTokenAmount = IERC20(bridgedTokenAddress).balanceOf(address(this)); _approve(bridgedTokenAddress, address(gateway), bridgedTokenAmount); gateway.sendToken(destinationChain, destinationAddress, bridgedTokenSymbol, bridgedTokenAmount); } function callBridgeCall( address token, uint256 amount, string calldata destinationChain, string calldata bridgedTokenSymbol, ISquidMulticall.Call[] calldata sourceCalls, ISquidMulticall.Call[] calldata destinationCalls, address refundRecipient, bool enableForecall ) external payable whenNotPaused { fundAndRunMulticall(token, amount, sourceCalls); address bridgedTokenAddress = gateway.tokenAddresses(bridgedTokenSymbol); _bridgeCall( destinationChain, bridgedTokenSymbol, bridgedTokenAddress, destinationCalls, refundRecipient, enableForecall ); } function contractId() external pure override returns (bytes32 id) { id = keccak256("squid-router"); } function fundAndRunMulticall( address token, uint256 amount, ISquidMulticall.Call[] memory calls ) public payable whenNotPaused { uint256 valueToSend; if (token == address(0)) { valueToSend = amount; } else { _transferTokenToMulticall(token, amount); } squidMulticall.run{value: valueToSend}(calls); } function _executeWithToken( string calldata, string calldata, bytes calldata payload, string calldata bridgedTokenSymbol, uint256 ) internal override { (ISquidMulticall.Call[] memory calls, address refundRecipient) = abi.decode( payload, (ISquidMulticall.Call[], address) ); address bridgedTokenAddress = gateway.tokenAddresses(bridgedTokenSymbol); uint256 contractBalance = IERC20(bridgedTokenAddress).balanceOf(address(this)); _approve(bridgedTokenAddress, address(squidMulticall), contractBalance); try squidMulticall.run(calls) { emit CrossMulticallExecuted(keccak256(payload)); } catch (bytes memory reason) { // Refund tokens to refund recepient if swap fails _safeTransfer(bridgedTokenAddress, refundRecipient, contractBalance); emit CrossMulticallFailed(keccak256(payload), reason, refundRecipient); } } function _bridgeCall( string calldata destinationChain, string calldata bridgedTokenSymbol, address bridgedTokenAddress, ISquidMulticall.Call[] calldata calls, address refundRecipient, bool enableForecall ) private { if (refundRecipient == address(0)) revert ZeroAddressProvided(); bytes memory payload = abi.encode(calls, refundRecipient); // Only works if destination router has same address string memory destinationContractAddress = address(this).toString(); uint256 bridgedTokenBalance = IERC20(bridgedTokenAddress).balanceOf(address(this)); if (address(this).balance > 0) { IAxelarGasService executionService = enableForecall ? forecallGasService : gasService; executionService.payNativeGasForContractCallWithToken{value: address(this).balance}( address(this), destinationChain, destinationContractAddress, payload, bridgedTokenSymbol, bridgedTokenBalance, refundRecipient ); } _approve(bridgedTokenAddress, address(gateway), bridgedTokenBalance); gateway.callContractWithToken( destinationChain, destinationContractAddress, payload, bridgedTokenSymbol, bridgedTokenBalance ); } function _approve( address tokenAddress, address spender, uint256 amount ) private { if (IERC20(tokenAddress).allowance(address(this), spender) < amount) { // Not a security issue since the contract doesn't store tokens IERC20(tokenAddress).approve(spender, type(uint256).max); } } function _transferTokenToMulticall(address token, uint256 amount) private { (bool success, bytes memory returnData) = token.call( abi.encodeWithSelector(IERC20.transferFrom.selector, msg.sender, address(squidMulticall), amount) ); bool transferred = success && (returnData.length == uint256(0) || abi.decode(returnData, (bool))); if (!transferred || token.code.length == 0) revert TransferFailed(); } function _setup(bytes calldata data) internal override { address _pauser = abi.decode(data, (address)); if (_pauser == address(0)) revert("Invalid pauser address"); _setPauser(_pauser); } }
{ "optimizer": { "enabled": true, "runs": 99999 }, "viaIR": true, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "metadata": { "useLiteralContent": true }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"name":"AlreadyInitialized","type":"error"},{"inputs":[],"name":"EtherNotAccepted","type":"error"},{"inputs":[],"name":"InvalidImplementation","type":"error"},{"inputs":[],"name":"NotOwner","type":"error"},{"inputs":[],"name":"SetupFailed","type":"error"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"implementation","outputs":[{"internalType":"address","name":"implementation_","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"implementationAddress","type":"address"},{"internalType":"address","name":"newOwner","type":"address"},{"internalType":"bytes","name":"params","type":"bytes"}],"name":"init","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"data","type":"bytes"}],"name":"setup","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
6080806040523461003957337f02016836a56b71f0d02689e69e326f4f4c1b9057164ef592671cf0d37c8040c05561069a908161003f8239f35b600080fdfe6080604052600436101561002c575b361561001f575b61001d6105f7565b005b610027610639565b610015565b6000803560e01c908163378dfd8e1461006b575080635c60da1b1461006257639ded06df0361000e5761005d61029f565b61000e565b5061005d61022d565b346101185760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610118576100a261011b565b6100aa610143565b6044359067ffffffffffffffff8211610114573660238301121561011457816004013592846100d8856101e4565b936100e66040519586610196565b8585523660248783010111610110578561010d9660246020930183880137850101526103b8565b80f35b5080fd5b8380fd5b80fd5b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361013e57565b600080fd5b6024359073ffffffffffffffffffffffffffffffffffffffff8216820361013e57565b507f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176101d757604052565b6101df610166565b604052565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f60209267ffffffffffffffff8111610220575b01160190565b610228610166565b61021a565b503461013e5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261013e5760207f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff60405191168152f35b503461013e5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261013e5760043567ffffffffffffffff80821161013e573660238301121561013e57816004013590811161013e573691016024011161013e57005b9081602091031261013e575190565b506040513d6000823e3d90fd5b60208082528251818301819052939260005b858110610374575050507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006040809697860101520116010190565b818101830151848201604001528201610334565b3d156103b3573d90610399826101e4565b916103a76040519384610196565b82523d6000602084013e565b606090565b91909173ffffffffffffffffffffffffffffffffffffffff917f02016836a56b71f0d02689e69e326f4f4c1b9057164ef592671cf0d37c8040c0938385541633036105cd577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc93808554166105a357600460207fc097d45e5a99ca772ab5ec2e5457c2e249760944b95b0b97cbb6b03ec55bae8492604051928380927f8291286c00000000000000000000000000000000000000000000000000000000825289165afa908115610596575b600091610568575b500361053e576000948386955555604051610500816104d460208201947f9ded06df00000000000000000000000000000000000000000000000000000000865260248301610322565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282610196565b51915af461050c610388565b501561051457565b60046040517f97905dfb000000000000000000000000000000000000000000000000000000008152fd5b60046040517f68155f9a000000000000000000000000000000000000000000000000000000008152fd5b610589915060203d811161058f575b6105818183610196565b810190610306565b3861048b565b503d610577565b61059e610315565b610483565b60046040517f0dc149f0000000000000000000000000000000000000000000000000000000008152fd5b60046040517f30cd7471000000000000000000000000000000000000000000000000000000008152fd5b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546000808092368280378136915af43d82803e15610635573d90f35b3d90fd5b5060046040517f37334834000000000000000000000000000000000000000000000000000000008152fdfea26469706673582212205a1ae4e4554ee5e5b30712df541f3571c30f56cc0963334dec2abbb4f5176f4d64736f6c63430008110033
Deployed Bytecode
0x6080604052600436101561002c575b361561001f575b61001d6105f7565b005b610027610639565b610015565b6000803560e01c908163378dfd8e1461006b575080635c60da1b1461006257639ded06df0361000e5761005d61029f565b61000e565b5061005d61022d565b346101185760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610118576100a261011b565b6100aa610143565b6044359067ffffffffffffffff8211610114573660238301121561011457816004013592846100d8856101e4565b936100e66040519586610196565b8585523660248783010111610110578561010d9660246020930183880137850101526103b8565b80f35b5080fd5b8380fd5b80fd5b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361013e57565b600080fd5b6024359073ffffffffffffffffffffffffffffffffffffffff8216820361013e57565b507f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176101d757604052565b6101df610166565b604052565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f60209267ffffffffffffffff8111610220575b01160190565b610228610166565b61021a565b503461013e5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261013e5760207f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff60405191168152f35b503461013e5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261013e5760043567ffffffffffffffff80821161013e573660238301121561013e57816004013590811161013e573691016024011161013e57005b9081602091031261013e575190565b506040513d6000823e3d90fd5b60208082528251818301819052939260005b858110610374575050507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8460006040809697860101520116010190565b818101830151848201604001528201610334565b3d156103b3573d90610399826101e4565b916103a76040519384610196565b82523d6000602084013e565b606090565b91909173ffffffffffffffffffffffffffffffffffffffff917f02016836a56b71f0d02689e69e326f4f4c1b9057164ef592671cf0d37c8040c0938385541633036105cd577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc93808554166105a357600460207fc097d45e5a99ca772ab5ec2e5457c2e249760944b95b0b97cbb6b03ec55bae8492604051928380927f8291286c00000000000000000000000000000000000000000000000000000000825289165afa908115610596575b600091610568575b500361053e576000948386955555604051610500816104d460208201947f9ded06df00000000000000000000000000000000000000000000000000000000865260248301610322565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282610196565b51915af461050c610388565b501561051457565b60046040517f97905dfb000000000000000000000000000000000000000000000000000000008152fd5b60046040517f68155f9a000000000000000000000000000000000000000000000000000000008152fd5b610589915060203d811161058f575b6105818183610196565b810190610306565b3861048b565b503d610577565b61059e610315565b610483565b60046040517f0dc149f0000000000000000000000000000000000000000000000000000000008152fd5b60046040517f30cd7471000000000000000000000000000000000000000000000000000000008152fd5b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546000808092368280378136915af43d82803e15610635573d90f35b3d90fd5b5060046040517f37334834000000000000000000000000000000000000000000000000000000008152fdfea26469706673582212205a1ae4e4554ee5e5b30712df541f3571c30f56cc0963334dec2abbb4f5176f4d64736f6c63430008110033
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
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.